10 advance list comprehensions

  • https://www.youtube.com/watch?v=twxE0dEp3qQ


  • General syntax of list comprehension:

     [ f(x)  for  x  in  list 
             if cond1
             if cond2
    	 ...
     ]
    

    Note: f(x) can be a conditional expression :

      val1(x) if cond(x) else val2(x)     # The else clause is mandatory
    
      This is equivalent to C's:  cond(x) ? val1(x) : val2(x)
    

Simple list comprehension

  • Get a list of values:

    values = []
    
    for x in range(10):
        values.append(x)
    


  • Solution with list comprehension:

    values = [ x for x in range(10) ]
    

    Output:

    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    

    You can write a for-loop inside of a list.

DEMO: progs/append01.py + append01-c.py

Generalized list comprehension

  • Simplest function with list comprehension:

    values = [ x for x in range(10) ]
    


  • In general, we can use any function of x:

    values = [ f(x) for x in range(10) ]
    

    Example:

    def square(x):
         return x**2
    
    values = [ square(x) for x in range(10) ]
    

DEMO: progs/append01-c2.py

Comprehension condition

  • Get the list of even values:

    evens = []
    
    for x in range(10):
        isEven = x % 2 == 0
        if isEven:
            evens.append(x)
    

  • Solution with list comprehension:

    evens = [ x for x in range(10) if (x%2 == 0) ]
    

    Output:

    0, 2, 4, 6, 8]
    

DEMO: progs/append02.py + append02-c.py

Comprehension with multiple conditions

  • Filter a list of strings and output only the ones that start with "a" and end in "y":

    input = ["any", "albany", "apple", "baby", ""]
    
    output = []       # Initialize output
    
    for x in input:
       if len(x) == 0:   # Protect illegal access of x[0] and x[-1]
          continue 
       if x[0] != "a":
          continue
       if x[-1] != "y":
          continue
       output.append(x)
    

  • Solution with list comprehension:

    output = [x 
                for x in input  # You can use a list instead of a for-loop
                if len(x) != 0
                if x[0] == "a"
                if x[-1] == "y"
             ]
    

DEMO: progs/filter01.py + filter01-c.py

Nested list comprehension

  • Flatten a matrix (= list of lists)

    matrix = [ [1, 2, 3], [4, 5, 6], [7, 8, 9] ]
    
    out = []
    
    for row in matrix:
        for num in row:
            out.append(num)
    

  • Solution with list comprehension:

    out = [num
               for row in matrix      # No  ":" !!!
                   for num in row
          ]
    
    

DEMO: progs/nested01.py + nested01-c.py

IF/ELSE inside a comprehension

  • Categorize a list of numbers as even or odd:

    input = [1, 2, 3, 4, 6]
    
    out = []
    
    for x in input:
        if x % 2 == 0:
            out.append("even")
        else:
            out.append("odd")
    

  • Solution with list comprehension:

    out = [ "even" if x % 2 == 0 else "odd"     # else-clause is required
                   for x in input
          ]
    

DEMO: progs/if-else01.py + if-else01-c.py + if-else01-c2.py

IF/ELSE inside a comprehension

  • Add 1 to all odd numbers in a list

    input = [1, 2, 3, 4, 6]
    
    out = []
    
    for x in input:
        if x % 2 == 0:
            out.append(x)
        else:
            out.append(x+1)    ### Add 1 when x is odd
    

  • Solution with list comprehension:

    out = [ x if x % 2 == 0 else x+1     # else-clause is required
              for x in input
          ]
    

DEMO: progs/if-else02-c.py

Nested list comprehension

  • Build a 3-dimensional list with list comprehension:

    out = []
    
    for a in range(3):
        l1 = []
        for b in range(4):
            l2 = []
            for x in range(2):
                l2.append(x)       ## [0 1]
            l1.append(l2)          ## [ [0 1]  [0 1]  [0 1] ]
        out.append(l1) 
    

  • Solution with list comprehension:

    out = [ [ [ 
                x  for x in range(2)
              ]
              for b in range(4)         ### We can use anonimous index var...
            ]
            for a in range(3)
          ]
    

How to read a nested list comprehension

  • Nested list comprehension:

    out = [ [ [ 
                x  for x in range(2)
              ]
              for b in range(4)         ### We can use anonimous index var...
            ]
            for a in range(3)
          ]
    

  • The most outer for-loop in the list comprehension is at the right:

    out = [ [ [                       
                x  for x in range(2)  
              ]                       
              for b in range(4)       
            ]                         
            for a in range(3)  Outer for-loop
          ]
    

  • The left-hand side of the for-loop will get added to the list (and recurse inside)

Dictionary comprehension

  • Syntax of a dictionary comprehension:

      {
         key: value    for  key, value  in  list
      }
    

  • Difference:

    • Use   { .... }   to enclose the for-loop

    • The elements before the for-loop is:

        f(k,v): g(k,v) 
      

    • The for-loop will use 2 indexes in a dictionary comprehension

Example of dictionary comprehension

  • Making a dictionary from a list of pairs:

     List of pairs:
    
        pairs = [ ("a", 1),  ("b", 2),  ("c", 3) ]
                  ^^^^^^^    ^^^^^^^    ^^^^^^^
                   pair 1     pair 2     pair 3 
    

  • How to create a dictionary using list comprehension:

    pairs = [ ("a", 1),  ("b", 2),  ("c", 3) ]   # List of pairs
    
    myDict  = { k: v   for  k,v in pairs }
    
    myDict2 = { k+str(v): v*v   for  k,v in pairs }
    

DEMO: progs/list2Dict01.py

Set comprehension

  • Syntax of a set comprehension:

      {
         value    for  value  in  list
      }
    

  • Difference:

    • Use   { .... }   to enclose the for-loop

    • The elements before the for-loop is:

        f(value)
      

    • The for-loop will use 1 index in a set comprehension

Example of set comprehension

  • Making a set (no duplicates) from a list:

     List of numbers:
    
        nums = [ 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4 ]    # List has duplicates
    

  • How to create a set using set comprehension:

    nums = [ 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4 ]
    
    mySet  = { x   for  x in nums }
    

DEMO: progs/list2Set01.py

Generators and lists

  • The expression:

        f(x)  for  x  in  range(1000000)
    

    is a generator (that returns a value when needed)

  • The expression:

        [ f(x)  for  x  in  range(1000000) ]
    

    is a list (object) (and all its values are stored)

DEMO: progs/genVSlist01.py + progs/genVSlist01b.py