Experimenting with List Comprehension (Python)

vegaseat 1 Tallied Votes 245 Views Share

A list comprehension derives a new list from an existing list, and was adopted by Python from the Haskell language. This snippet tries to explain the development of list comprehension and shows a number of uses, including nested list comprehension. The benefits are simplicity (after an initial learning bump) and in most cases speed improvements.

# experiments with list comprehension
# tested with Python24      vegaseat    02feb2006

import random    # random.sample(), random.shuffle()
import textwrap  # textwrap.fill()
import string    # string.punctuation

# create a list of integer numbers
numList = range(24)
print "List of numbers 0 to 23:"
print numList

# this shows you the development of list comprehension
# creating a list of odd numbers from the above list
# the traditional way, no list comprehension ...
oddList1 = []
for x in numList:
    if x % 2 != 0:
        oddList1.append(x)
        
# interim version of list comprehension ...
# (uses all the above statements)
# notice that the total list comprehension is enclosed in [  ]
oddList2 = []
[oddList2.append(x) for x in numList if x % 2 != 0]

# final (simplified) version of list comprehension ...
oddList3 = [x for x in numList if x % 2 != 0]

# test the results
print "\nList of odd numbers from 1 to 23:"
print "oddList1 =", oddList1
print "oddList2 =", oddList2
print "oddList3 =", oddList3

print

# get the maximum integer less or equal to a given integer
def max_le(seq, val):
    '''return max element of sequence less than or equal to val'''
    return max([v for v in seq if v <= val])

# create a list of 10 random integers in the range 0 to 99 and test max_le()
randomList = random.sample(xrange(100), 10)
print randomList
try:
    num = 7
    result = max_le(randomList, num)
    print "Maximum integer less or equal to %d in above list: %d" % (num, result)
except:
    print "All numbers in the above list exceed %d" % num

print

# create a deck of cards:
cards = [suit + rank for suit in "CDHS" for rank in "A23456789TJQK"]
print "Show the first 13 cards (suit + rank  eg. CA = ace of club, CT = ten of club):"
print cards[:13]  # ['CA', 'C2', 'C3', 'C4', 'C5', 'C6', 'C7', 'C8', 'C9', 'CT', 'CJ', 'CQ', 'CK']
# shuffle the cards:
random.shuffle(cards)
print "Show a hand of 5 shuffled cards:"
hand = cards[:5]
print hand
print "Hand sorted by suit:"
print sorted(hand)

# to sort by rank you can change to rank + suit (eg. C7 becomes 7C) then sort
# again, list comprehension is used
hand1 = sorted([card[1:2] + card[0:1] for card in hand])
#print hand1  # test
# change back to suit + rank (7C changes back to C7)
hand2 = [card[1:2] + card[0:1] for card in hand1]
print "Hand sorted by rank:"
print hand2

print

# list pi values progressively rounded off
print "List of pi values progressively rounded off:"
piList = [str(round(355/113.0, k)) for k in range(1,6)]
print piList

print

# use list comprehension to remove duplicate elements
gwb = "We got into deficit because the economy went into the recession that is how we got into deficit"
rawList = gwb.split()
print "The raw list containing duplicates:"
print rawList
# create an empty list
uniqueList = []
[uniqueList.append(str1) for str1 in rawList if not uniqueList.count(str1)]
print "\nThe unique list (no duplicates):"
print uniqueList

print

# remove leading and trailing spaces from strings
fruitList = ['  banana', '  loganberry ', 'passion fruit  ']
print "Original list = ", fruitList
stripList = [fruit.strip() for fruit in fruitList]
print "Stripped leading/trailing spaces = ", stripList

print

print "Remove punctuation marks from a string:"
str1 = "47 years ago '_jitter' was almost '_chatter', how about that?"
str2 = "".join([c for c in str1 if c not in string.punctuation])
print str1
print str2

print

# use list comprehension to compare two lists
list1 = [1, 2, 5, 7, 12, 25, 32, 47, 65, 99]
list2 = [1, 2, 5, 7, 12, 15, 32, 48, 65, 99]
print "list1 =", list1
print "list2 =", list2
print "These are the items different in the two lists:"
print [(x, y) for (x, y) in zip(list1, list2) if x != y]

print

# creating a 10x10 matrix (list of lists)
# first create a list of ten elements
myList = range(10)
# now create a 10x10 matrix of zeros using a nested list comprehension
myMatrix = [[0 for k in myList] for k in myList]

print "A 10x10 matrix (list of lists) of zeros:"
print myMatrix
print "Improved display:"
for k in myMatrix:
    print k

# insert 1 as a "ulc to lrc diagonal"
for k in range(10):
    myMatrix[k][k] = 1
    
# display the result
print "Added a diagonal of ones:"
for k in myMatrix:
    print k

print

# convert this string into a list of words
str1 = \
"""The dynamic declination flag was accidentally switched to EIEIO. Check your atomic memory
pool for floaters because they're probably causing the kernel to pop. But be careful because
the memory manager is volatile and could cause the entire pipeline to dump core unexpectedly.
"""
wordList = str1.split(None)

# cut the list of words into a list of lists of 5 words or less each
cutWordList2 = [wordList[k:k+5] for k in range(0, len(wordList), 5)]

# display the result as text (max 5 words per line)
print "Text shown with max 5 words per line:"
for subList in cutWordList2:
    line = " ".join(subList)
    print line

print

# a word/text wrap that preserves existing line breaks and spaces
# uses the module textwrap and list comprehension
print "Wrap the text into 35 column space:"
sep = "\n\n"
print "-"*35
print sep.join([textwrap.fill(line, 35) for line in str1.split(sep)])
print "-"*35