Python 3.6 [PY36 Env]

List Comprehension Examples

These examples illustrate use of list comprehensions. These examples are tested in Python 3.6 but should work in 2.7 as well.

Simple Examples


In [10]:
# libraries used in the Notebook
import numpy as np

In [13]:
[i for i in range(3,10)]  # in real code, range(3,10) would probably be a list or iterable that is the source


Out[13]:
[3, 4, 5, 6, 7, 8, 9]

In [17]:
print([i for i in range(3,10)])
[i**2 for i in range(3,10) if i > 6]  # squares all values in range(3,10) but only if original value was > 6


[3, 4, 5, 6, 7, 8, 9]
Out[17]:
[49, 64, 81]

In [2]:
# example from stack overflow: [x+1 if x >= 45 else x+5 for x in l]
[i**2 if i > 6 else i for i in range(3,10)]  # squares all values in range(3,10) original value was > 6 else output original


Out[2]:
[3, 4, 5, 6, 49, 64, 81]

More Complex or Specific Examples

Demonstration Accessing Index and Value of List & if/else


In [1]:
# this function solves converting a number to a string with commas for thousands separators
# using a single list comprehension to do it.  The following sample code helped in writing this:
#      * Example of enumerate to get value,index: [(value, ind) for ind, value in enumerate(Lst)]
#      * Example of if/else: [i for i in Lst[:-1] if (((i+1) - (i))/(i)) > 0.08 else ... (condition here)] 

def thousands_with_commas(integer):
    strng = str(integer)    
    return ''.join([',' + str(value) if (len(strng) - ind) % 3 == 0 and ind > 0 
            else value for ind, value in enumerate(strng)])

## tests:
print(thousands_with_commas(1234))
print(thousands_with_commas(12))
print(thousands_with_commas(123456789))
print(thousands_with_commas(1234567890))


1,234
12
123,456,789
1,234,567,890

Misc. Complex Examples


In [8]:
# working with nested lists:

tstLst = [['1','2.0','3.5'],['0.0','-5.789', '666'],['13.7']]

out1 = [[float(y) for y in x] for x in tstLst]   # convert to float, output in original nested structure
out2 = [float(y) for x in tstLst for y in x]     # convert to float, output as flat single list
out3 = [float(y) for x in tstLst for y in x if float(y) > 13]                     # combine with if test
out4 = [[float(y) for y in x if float(y) > 13 or float(y) < 1] for x in tstLst]   # combine w/ if test

print(out1)
print(out2)
print(out3)
print(out4)


[[1.0, 2.0, 3.5], [0.0, -5.789, 666.0], [13.7]]
[1.0, 2.0, 3.5, 0.0, -5.789, 666.0, 13.7]
[666.0, 13.7]
[[], [0.0, -5.789, 666.0], [13.7]]

In [4]:
# finding second biggest number in a list
arr = [14, 400, 35, 17, 34, 399, 0, 77]
print(max([a for a in arr if a != max(arr)]))


399

In [2]:
# example of cross-tab query like list comprehension (from two lists) found on Stack Overflow

list1 = [1, 2, 3]
list2 = [40, 50]
vals=[(x,y) for x in list1 for y in list2]
print(list1)
print(list2)
print(vals)


[1, 2, 3]
[40, 50]
[(1, 40), (1, 50), (2, 40), (2, 50), (3, 40), (3, 50)]

In [1]:
# Not best practice, but printing from within a list comprehension and using enumerate

listofints = [1,2,3,9,10,11,12,19,99,100,101,102, 999, 1000, 1001, 50102030]
# note:  printing from within a list comprehension is criticized online as being "not pythonic" 
#        concepts illustrated:
#          * ind, x  in enumerate(list) ==> how to get index and value
#          * (x, print())[0] ==> x is output using [0] to grab just first element of output, print then happens from [1]
#          * tempLst is capturing element [0] only
#          * print is probably returning None but element [1] (the return value) is not captured in tempLst

tempLst = [((x, listofints[ind+1]), print(x, listofints[ind+1]))[0] 
           for ind, x in enumerate(listofints) if ind < len(listofints)-1]

print("\ntempLst:\n%s" %tempLst)


1 2
2 3
3 9
9 10
10 11
11 12
12 19
19 99
99 100
100 101
101 102
102 999
999 1000
1000 1001
1001 50102030

tempLst:
[(1, 2), (2, 3), (3, 9), (9, 10), (10, 11), (11, 12), (12, 19), (19, 99), (99, 100), (100, 101), (101, 102), (102, 999), (999, 1000), (1000, 1001), (1001, 50102030)]

In [12]:
# this example was used in a function to test that all values in an array
# are between an allowed range (sample arrays and just the relavent code excerpt provided here)

# because of any(), if any of the values in the list comprehension are True, the condition is True,
#                   if the list comprehension finds no matches, the list comprehension is empty and
#                   any() evaluates empty as False

import numpy as np

arr = np.array([[0,0,0,0,0,0],
                [1,2,3,4,5,6],
                [8,7,5,2,1,1],
                [1,1,1,1,1,1],
                [0,9,1,5,3,3],
                [7,7,7,7,7,7]])


arr2 = np.array([[0,0,0,0,0,0],
                 [1,2,3,4,5,6],
                 [8,7,5,2,1,1],
                 [1,1,1,1,1,1],
                 [0,9,11,5,3,3],
                 [7,7,7,7,7,-10]])

# try / except allows the if condition to raise errors as appropriate without halting the notebook if you re-run it

try:
    if any([True for x in arr for y in x if y < -9 or y > 9]):
        raise ValueError("Error in arr: All Values in array must be between -9 and 9.")
    else:
        print("arr array values are all within the acceptable range.")
        
except ValueError as ve:
    print(type(ve))
    print(ve)
    
try:
    if any([True for x in arr2 for y in x if y < -9 or y > 9]):
        raise ValueError("Error in arr2: All Values in array must be between -9 and 9.")
    else:
        print("arr2 array values are all within the acceptable range.")
except ValueError as ve:
    print(type(ve))
    print(ve)


arr array values are all within the acceptable range.
<class 'ValueError'>
Error in arr2: All Values in array must be between -9 and 9.

Some Examples from Hackerrank

Many of these examples combine nesting of the list comprehension syntax with other concepts. The problems come from hackerrank.

The Constrained Cuboid

This example organizes x, y, z in a cuboid and uses n to constrain the output by what each row adds up to.


In [3]:
# the "constrained cuboid" was a hackerrank problem
# the constraint causes the cuboid code to skip outputting sublists in the cuboid array that add up to the constraint number
# set the contraint high enough, and you will see what an unconstrained cuboid looks like since no sublists will meet
# the constraint criteria then

def constrainedCuboid(x, y, z, n_constraint):
    return [[x1,y1,z1] for x1 in range(x+1) 
            for y1 in range(y+1) 
            for z1 in range(z+1) if x1+y1+z1 != n_constraint]  # 3 levels of nesting within the list comprehension

In [6]:
print(constrainedCuboid(1, 2, 4, 6))      # constrained: show only subsets that sum to less than 6
print("---------------------------")
print(constrainedCuboid(1, 2, 4, 1000))   # unconstrained:  all subsets will sum to less than 1000 so all will be output
print("----------------------------")


[[0, 0, 0], [0, 0, 1], [0, 0, 2], [0, 0, 3], [0, 0, 4], [0, 1, 0], [0, 1, 1], [0, 1, 2], [0, 1, 3], [0, 1, 4], [0, 2, 0], [0, 2, 1], [0, 2, 2], [0, 2, 3], [1, 0, 0], [1, 0, 1], [1, 0, 2], [1, 0, 3], [1, 0, 4], [1, 1, 0], [1, 1, 1], [1, 1, 2], [1, 1, 3], [1, 2, 0], [1, 2, 1], [1, 2, 2], [1, 2, 4]]
---------------------------
[[0, 0, 0], [0, 0, 1], [0, 0, 2], [0, 0, 3], [0, 0, 4], [0, 1, 0], [0, 1, 1], [0, 1, 2], [0, 1, 3], [0, 1, 4], [0, 2, 0], [0, 2, 1], [0, 2, 2], [0, 2, 3], [0, 2, 4], [1, 0, 0], [1, 0, 1], [1, 0, 2], [1, 0, 3], [1, 0, 4], [1, 1, 0], [1, 1, 1], [1, 1, 2], [1, 1, 3], [1, 1, 4], [1, 2, 0], [1, 2, 1], [1, 2, 2], [1, 2, 3], [1, 2, 4]]
----------------------------

In [14]:
# for cleaner output, we could use a list comprehension
# we can also output the sum of each sub element to show the constraint in action

print("Constrained:")
[print("Sum(" + str(elem) + (") = %d" %sum(elem))) for elem in constrainedCuboid(1, 2, 4, 6)]     
print("---------------------------")
print("Unconstrained:")
[print("Sum(" + str(elem) + (") = %d" %sum(elem))) for elem in constrainedCuboid(1, 2, 4, 1000)]     
print("---------------------------")


Constrained:
Sum([0, 0, 0]) = 0
Sum([0, 0, 1]) = 1
Sum([0, 0, 2]) = 2
Sum([0, 0, 3]) = 3
Sum([0, 0, 4]) = 4
Sum([0, 1, 0]) = 1
Sum([0, 1, 1]) = 2
Sum([0, 1, 2]) = 3
Sum([0, 1, 3]) = 4
Sum([0, 1, 4]) = 5
Sum([0, 2, 0]) = 2
Sum([0, 2, 1]) = 3
Sum([0, 2, 2]) = 4
Sum([0, 2, 3]) = 5
Sum([1, 0, 0]) = 1
Sum([1, 0, 1]) = 2
Sum([1, 0, 2]) = 3
Sum([1, 0, 3]) = 4
Sum([1, 0, 4]) = 5
Sum([1, 1, 0]) = 2
Sum([1, 1, 1]) = 3
Sum([1, 1, 2]) = 4
Sum([1, 1, 3]) = 5
Sum([1, 2, 0]) = 3
Sum([1, 2, 1]) = 4
Sum([1, 2, 2]) = 5
Sum([1, 2, 4]) = 7
---------------------------
Unconstrained:
Sum([0, 0, 0]) = 0
Sum([0, 0, 1]) = 1
Sum([0, 0, 2]) = 2
Sum([0, 0, 3]) = 3
Sum([0, 0, 4]) = 4
Sum([0, 1, 0]) = 1
Sum([0, 1, 1]) = 2
Sum([0, 1, 2]) = 3
Sum([0, 1, 3]) = 4
Sum([0, 1, 4]) = 5
Sum([0, 2, 0]) = 2
Sum([0, 2, 1]) = 3
Sum([0, 2, 2]) = 4
Sum([0, 2, 3]) = 5
Sum([0, 2, 4]) = 6
Sum([1, 0, 0]) = 1
Sum([1, 0, 1]) = 2
Sum([1, 0, 2]) = 3
Sum([1, 0, 3]) = 4
Sum([1, 0, 4]) = 5
Sum([1, 1, 0]) = 2
Sum([1, 1, 1]) = 3
Sum([1, 1, 2]) = 4
Sum([1, 1, 3]) = 5
Sum([1, 1, 4]) = 6
Sum([1, 2, 0]) = 3
Sum([1, 2, 1]) = 4
Sum([1, 2, 2]) = 5
Sum([1, 2, 3]) = 6
Sum([1, 2, 4]) = 7
---------------------------

In [7]:
# use this cell to input your own numbers and see results
if __name__ == '__main__':
    # inputs used for original testing:  1,2,4,6   and   1,2,4,1000
    #                                    3,3,3,5
    x = int(input())
    y = int(input())
    z = int(input())
    n = int(input())

print(constrainedCuboid(x, y, z, n))


1
2
4
6
[[0, 0, 0], [0, 0, 1], [0, 0, 2], [0, 0, 3], [0, 0, 4], [0, 1, 0], [0, 1, 1], [0, 1, 2], [0, 1, 3], [0, 1, 4], [0, 2, 0], [0, 2, 1], [0, 2, 2], [0, 2, 3], [1, 0, 0], [1, 0, 1], [1, 0, 2], [1, 0, 3], [1, 0, 4], [1, 1, 0], [1, 1, 1], [1, 1, 2], [1, 1, 3], [1, 2, 0], [1, 2, 1], [1, 2, 2], [1, 2, 4]]

Simple Email Address Validation Example

This code shows how a multi-line task (without the list comprehension) condenses down to a single line list comprehension that gets user input from within its nesting conditions. Readability is definitely sacrificed for what the list comprehension may gain us in terms of speed and succinctness of code.


In [2]:
import sys

lst = []
N = int(input().strip())
for eachOne in range(N):
    firstName, emailID = input().strip().split(' ')
    firstName, emailID = [str(firstName),str(emailID)]
    
    if emailID[-10:] == "@gmail.com":
        lst.append(firstName)

print("----------------------") # this line will be lost in our list comprehension example that follows
print("\n".join(sorted(lst)))


9
Joe JoesDiner@gmail.com
Fred fredAtJoesDiner@joesDiner.someDomain.com
Lindsay Lindsay.Drunken.Lohan@gmail.com
Arthur Arthur.Dent@UniverseEnd.net
suzy SuzyQ@gmail.com
Laura LauraLinly@gmail.co
warren WarrenBuffet@gmail.me
Ford Ford.Prefect@gmail.com
dim dim.wit.nation@Trump4President.com
----------------------
Ford
Joe
Lindsay
suzy

In [3]:
import sys
print("\n".join(sorted([l.split()[0] for l in [input() for _ in range(int(input()))] if '@gmail.com' in l])))
             # more accurate:
             #     end the code like this:                                           if l[-10:] == '@gmail.com'


9
Joe JoesDiner@gmail.com
Fred fredAtJoesDiner@joesDiner.someDomain.com
Lindsay Lindsay.Drunken.Lohan@gmail.com
Arthur Arthur.Dent@UniverseEnd.net
suzy SuzyQ@gmail.com
Laura LauraLinly@gmail.co
warren WarrenBuffet@gmail.me
Ford Ford.Prefect@gmail.com
dim dim.wit.nation@Trump4President.com
Ford
Joe
Lindsay
suzy