This article needs additional citations for verification .(February 2009) |
List comprehension is a syntactic construct available in some programming languages for creating a list based on existing lists. It follows the form of the mathematical set-builder notation (set comprehension) as distinct from the use of map and filter functions.
List with all the doubles from 0 to 10 (exclusive)
doubles=[i*2foriinrange(10)]
List with the names of the customers based in Rio de Janeiro
rjCustomers=[customer.Nameforcustomerincustomersifcustomer.State=="RJ"]
varns=fromxinEnumerable.Range(0,100)wherex*x>3selectx*2;
The previous code is syntactic sugar for the following code written using lambda expressions:
varns=Enumerable.Range(0,100).Where(x=>x*x>3).Select(x=>x*2);
Filtering numbers divisible by 3:
valuedivisibleBy3={for(iin0..100)if(i%3==0)i};// type of divisibleBy3 is Iterable<Integer>
Multiple "generators":
valuetriples={for(xin0..20)for(yinx..20)for(ziny..20)if(x*x+y*y==z*z)[x,y,z]};// type of triples is Iterable<Integer[3]>
An infinite lazy sequence:
(for[x(iterateinc0):when(>(*xx)3)](*2x))
A list comprehension using multiple generators:
(for[x(range20)y(range20)z(range20):when(==(+(*xx)(*yy))(*zz))][xyz])
largeNumbers=(numberfornumberinlistwhennumber>100)
List comprehensions can be expressed with the loop
macro's collect
keyword. Conditionals are expressed with if
, as follows:
(loopforxfrom0to100if(>(*xx)3)collect(*2x))
List the names of customers:
names=forcustincustomersgetcust.name
List the customers with balances:
names=forcustincustomerswherecust.balance>0
List the names of customers with balances:
names=forcustincustomerswherecust.balance>0getcust.name
The general forms:
forVARinENUMERABLE[whereCONDITION]getEXPRforVARinENUMERABLEwhereCONDITION
Note that by putting the condition and expression after the variable name and enumerable object, editors and IDEs can provide autocompletion on the members of the variable.
[for(variinrange(0,100))if(i*i>3)i*2]
varpyth=[for(varxinrange(1,20))for(varyinrange(x,20))for(varzinrange(y,20))if(x*x+y*y==z*z)[x,y,z]];
Iterable<int>range(intstart,intend)=>List.generate(end-start,(i)=>start+i);
forx<-0..100,x*x>3,do:x*2
L=lists:seq(0,100).S=[2*X||X<-L,X*X>3].
Lazily-evaluated sequences:
seq{forxin0..100doifx*x>3thenyield2*x}
Or, for floating point values
seq{forxin0...100.doifx**2.>3.thenyield2.*x}
Lists and arrays:
[forxin0...100.doifx**2.>3.thenyield2.*x][|forxin0...100.doifx**2.>3.thenyield2.*x|]
List comprehensions are the part of a greater family of language constructs called computation expressions.
[x*2|x<-[0..99],x*x>3]
An example of a list comprehension using multiple generators:
pyth=[(x,y,z)|x<-[1..20],y<-[x..20],z<-[y..20],x^2+y^2==z^2]
By using Range object, Io language can create list as easy as in other languages:
Range0to(100)asListselect(x,x*x>3)map(*2)
List comprehensions can be expressed with the for
special form. Conditionals are expressed with if
, as follows:
(for((x0(+x1))(collect()))((>=x100)(reversecollect))(if(>(*xx)3)(setqcollect(cons(*x2)collect))))
Julia supports comprehensions using the syntax:
y=[x^2+1forxin1:10]
and multidimensional comprehensions like:
z=[(x-5)^2+(y-5)^2forx=0:10,y=0:10]
It is also possible to add a condition:
v=[3x^2+2y^2forxin1:7foryin1:7ifx%y==0]
And just changing square brackets to the round one, we get a generator:
g=(3x^2+2y^2forxin1:7foryin1:7ifx%y==0)
s = [ 2*i for i in 1..100 where i*i > 3 ];
Multiple generators:
pyth = [ (x,y,z) for x in 1..20 for y in x..20 for z in y..20 where x*x + y*y == z*z ];
$[x*2|xin[0..100],x*x>3]
Nim has built-in seq, set, table and object comprehensions on the sugar standard library module: [1]
importsugarletvariable=collect(newSeq):foritemin@[-9,1,42,0,-1,9]:item+1assertvariable==@[-8,2,43,1,0,10]
The comprehension is implemented as a macro that is expanded at compile time, you can see the expanded code using the expandMacro compiler option:
varcollectResult=newSeq(Natural(0))foriteminitems(@[-9,1,42,0,-1,9]):add(collectResult,item+1)collectResult
The comprehensions can be nested and multi-line:
importsugarletvalues=collect(newSeq):forvalin[1,2]:collect(newSeq):forval2in[3,4]:if(val,val2)!=(1,2):(val,val2)assertvalues==@[@[(1,3),(1,4)],@[(2,3),(2,4)]]
OCaml supports List comprehension through OCaml Batteries. [2]
my@s=map{2*$_}grep{$_**2>3}0..99;
Array with all the doubles from 1 to 9 inclusive:
my@doubles=map{$_*2}1..9;
Array with the names of the customers based in Rio de Janeiro (from array of hashes):
my@rjCustomers=map{$_->{state}eq"RJ"?$_->{name}:()}@customers;
Filtering numbers divisible by 3:
my@divisibleBy3=grep{$_%3==0}0..100;
$s=(0..100|?{$_*$_-gt3}|%{2*$_})
which is short-hand notation of:
$s=0..100|where-object{$_*$_-gt3}|foreach-object{2*$_}
Python uses the following syntax to express list comprehensions over finite lists:
S=[2*xforxinrange(100)ifx**2>3]
A generator expression may be used in Python versions >= 2.4 which gives lazy evaluation over its input, and can be used with generators to iterate over 'infinite' input such as the count generator function which returns successive integers:
fromitertoolsimportcountS=(2*xforxincount()ifx**2>3)
(Subsequent use of the generator expression will determine when to stop generating values).
x<-0:100S<-2*x[x^2>3]
(for/list([x100]#:when(>(*xx)3))(*x2))
An example with multiple generators:
(for*/list([x(in-range121)][y(in-range121)][z(in-range121)]#:when(=(+(*xx)(*yy))(*zz)))(listxyz))
my@s = ($_ * 2if$_ ** 2 > 3for0 .. 99);
Using the for-comprehension:
vals=for(x<-0to100;ifx*x>3)yield2*x
List comprehensions are supported in Scheme through the use of the SRFI-42 library. [3]
(list-ec(:x100)(if(>(*xx)3))(*x2))
An example of a list comprehension using multiple generators:
(list-ec(:x121)(:yx21)(:zy21)(if(=(+(*xx)(*yy))(*zz)))(listxyz))
s := {2*x : x in {0..100} | x**2 > 3 };
((1to:100) select: [ :x|xsquared>3 ]) collect: [ :x|x*2 ]
S = [2*X||X = list::getMember_nd(L), X*X>3]