“List Comprehension” in Python, and Perl

Python

2005-02-11

David Eppstein of the Geometry Junkyard fame gave this elegant version for returning all possible pairs from a range of n numbers.

def combo2(n):
    return dict([('%d,%d'%(i,j),(i,j)) for j in range(1,n+1) for i in range(1,j)])

print combo2(3) # prints
# {'3,4': (3, 4), '1,4': (1, 4), '1,2': (1, 2), '1,3': (1, 3), '2,4': (2, 4), '2,3': (2, 3)}

This construct uses a irregular syntax (called “list comprehension”) to generate a expression normally built by nested loops. This construct has acquired a incomprehensible name “list comprehension” in computing industry and academia.

In Python, this syntax irregularity works like this, for example, generating a list of i*2 with i from 1 to 5:

myList = [ i*2 for i in range(1,6)]
print myList

Another example: To built a list of couples of the form (i*2,i*3):

myList = [ (i*2,i*3) for i in range(1,6)]
print myList

In general this expression generating syntax has the form “[‹expression› ‹iteration›]” where the “‹expression›” contains some variables in “‹iteration›” , and the result of each loop is put into a list.

The iteration part can be nested. Example:

# python

myList = [ (i,j) for i in range(1,6) for j in range(1,4)]
print myList
# prints [(1, 1), (1, 2), (1, 3), (2, 1), (2, 2), (2, 3), (3, 1), (3,
# 2), (3, 3), (4, 1), (4, 2), (4, 3), (5, 1), (5, 2), (5, 3)]

Remember, this jargonized “list comprehension” is nothing more than a irregular syntax for building a list from loops. Its purpose is purely of syntactical convenience. Advanced languages such as functional languages often have this power without the syntax irregularity. (For example, Mathematica's Table function.)

Mathematica: Table

Python Doc

Perl

Perl the language does not have the “list comprehension” per se. (However, in general, functional programing's brevity is more easily achieved in perl than python.)

Here's a example of generating a list of i*2 for i from 1 to 5:

# perl

@myList = map {$_ * 2} (1..5);

use Data::Dumper;
print Dumper(\@myList);

Here's a example of generating a list of pairs “[i*2,i*3]”.

# perl

@myList = map {[$_ * 2, $_ * 3]} (1..5);

use Data::Dumper;
print Dumper(\@myList);

Here's a example of generating a nested list involving 2 looping variables that's normally done with “list comprehension”. In perl, it's just done with normal nested loops.

# perl
@myList=();
for ($i=1;$i<=5;$i++) {
  for ($j=1;$j<=3;$j++) {
    push (@myList, [$i,$j]);
  }
}

use Data::Dumper; $Data::Dumper::Indent=0;
print Dumper(\@myList);

# prints $VAR1 = [[1,1],[1,2],[1,3],[2,1],[2,2],[2,3],
# [3,1],[3,2],[3,3],[4,1],[4,2],[4,3],[5,1],[5,2],[5,3]];

Note: Mathematica's Table function is a list generator and is far more powerful than the so-called “list comprehension”. For a perl version of Mathematica's Table: See http://xahlee.org/tree/Table.html

Related essays:

2005-02
© 2005 by Xah Lee.