Reputation: 452
Example:
for x in iterable1:
expression
The map
form would be:
map(lambda x: expression, iterable1)
How do I extend this to a nested for loop using only map
and without list comprehensions?
Example:
for x in itr1:
for y in itr2:
expr
Upvotes: 6
Views: 10025
Reputation: 23144
for x in itr1:
for y in itr2:
expr(x, y)
This roughly corresponds to
map(lambda t: expr(t[0], t[1]), ((x, y) for x in itr1 for y in itr2))
Note that in Python 3 you cannot use unpacking of tuple arguments in lambda (i.e. you cannot write lambda x, y: expr(x, y)
here) and have to use indexing: Python lambda does not accept tuple argument
For example:
>>> m = map(lambda t: t[0] + t[1], ((x, y) for x in "abc" for y in "def"))
>>> for v in m:
... print(v, end=" ")
...
ad ae af bd be bf cd ce cf
can be used instead of:
>>> for x in "abc":
... for y in "def":
... print(x + y, end=" ")
...
ad ae af bd be bf cd ce cf
Upvotes: 0
Reputation: 1
I came across the same problem, and using nested list comprehensions or itertools felt like cheating since I knew it is possible to do it with only higher order functions.
So this is my solution:
from functools import reduce
cross_prod = lambda li1, li2: reduce(lambda s, x: s + list(map(lambda y: (x, y), li2)), li1, [])
print(cross_prod(range(3), range(10, 13)))
Upvotes: 0
Reputation: 452
Bear with me on this one. Not an explanation but this worked after 2 days. Using only map and list. It's bad code. Suggestions to shorten the code are welcome. Python 3 solution
Example using list comprehension:
>>> a=[x+y for x in [0,1,2] for y in [100,200,300]]
>>> a
[100,200,300,101,201,301,102,202,302]
Example using for:
>>>a=[]
>>>for x in [0,1,2]:
... for y in [100,200,300]:
... a.append(x+y)
...
>>>a
[100,200,300,101,201,301,102,202,302]
Now example using only map:
>>>n=[]
>>>list(map(lambda x:n.extend(map(x,[100,200,300])),map(lambda x:lambda y:x+y,[0,1,2])))
>>>n
[100,200,300,101,201,301,102,202,302]
Much smaller python2.7 solution:
>>>m=[]
>>>map(lambda x:m.extend(x),map(lambda x:map(x,[100,200,300]),map(lambda x:lambda y:x+y,[0,1,2])))
>>>m
[100,200,300,101,201,301,102,202,302]
Another variation : I emailed to Mark Lutz and this was his solution. This doesn't use closures and is the closest to nested for loops functionality.
>>> X = [0, 1, 2]
>>> Y = [100, 200, 300]
>>> n = []
>>> t = list(map(lambda x: list(map(lambda y: n.append(x + y), Y)),X))
>>> n
[100,200,300,101,201,301,102,202,302]
Upvotes: 2
Reputation: 32590
You could use itertools.product
to build the cartesian product of your two nested sequences, and map
your expression to the that list of 2-tuples:
from itertools import product
map(lambda (x, y): expression, product(itr1, itr2))
Example with some actual values:
seq = map(lambda (x, y): '%s:%s' % (x, y), product(itr1, itr2))
for item in seq:
print item
Note that the lambda (x, y)
is necessary to unpack each 2-tuple from the sequence to the separate x
and y
arguments used in the expression.
Upvotes: 7
Reputation: 37023
You can't. The lambda
is specifically limited to functions whose return value can be encapsulated as a single expression: statements aren't allowed.
One question you should ask yourself is why do you think this would be a desirable way to write a Python program? The language has been explicitly defined for readability, and you should do everything you can to maintain that readability.
Upvotes: 1