Reputation: 645
Is there a way to unpack a tuple with the *
idiom when using the map
built-in in Python?
Ideally, I'd like to do the following:
def foo(a, b):
return a**2 + b
x = [(1,2), (3,4), (5,6)]
results = map(foo, *x)
where results would equal [3, 13, 31]
Upvotes: 2
Views: 109
Reputation: 61635
As it happens, map
accepts *args, so your original call map(foo, *x)
doesn't immediately fail - but what happens is that each element from x
is treated as a sequence of values for one argument to foo
- so it attempts foo(1, 3, 5)
and would then attempt foo(2, 4, 6)
except of course that foo
only accepts 2 arguments.
Since we can see that our input x
is effectively the "matrix transpose" of what we would like to feed in, that directly points us to a workaround:
>>> list(map(foo, *zip(*x))) # list() wrapping for 3.x support
[3, 13, 31]
... But don't do that. Use itertools.starmap
; it's built for this and considerably clearer about your intent.
Upvotes: 1
Reputation: 6575
An uglier way than the @roippi's way...
x = [(1,2), (3,4), (5,6)]
map(lambda y:y[0]**2 + y[1], x)
Upvotes: 1
Reputation: 25974
You're looking for itertools.starmap
:
def foo(a, b):
return a**2 + b
x = [(1,2), (3,4), (5,6)]
from itertools import starmap
starmap(foo, x)
Out[3]: <itertools.starmap at 0x7f40a8c99310>
list(starmap(foo, x))
Out[4]: [3, 13, 31]
Note that even in python 2, starmap
returns an iterable that you have to manually consume with something like list
.
Upvotes: 7