list comprehension for multiple return function?
Solution 1
First of all, you made a small mistake: it should be:
[f(value) for value in x]
# ^ notice the `value`
instead of:
[f(x) for value in x]
Furthermore the point is that:
return 2*x,x
is short for:
return (2*x,x)
so a tuple. Your list comprehension thus generates a list of tuples, not a tuple of lists. The nice thing of zip
however is that you can easily use it in reverse with the asterisk:
xlist,ylist = zip(*[f(value) for value in x])
# ^ with asterisk
Note that xlist
and ylist
will be tuples (since zip
will be unpacked). If you want them to be lists, you can for instance use:
xlist,ylist = map(list,zip(*[f(value) for value in x]))
which results in:
>>> xlist
[0, 2, 4]
>>> ylist
[0, 1, 4]
(note that range
s start counting from 0)
Alternative: Another way to do this is of course:
xlist = [f(value)[0] for value in x]
ylist = [f(value)[1] for value in x]
But this is of course inelegantly and furthermore can be inefficient (given f
is computationally expensive).
Solution 2
Let's make this work. The function is fine:
def f(x):
return 2*x, x*x
But you want to define the range as follows, notice the starting and ending values:
x = range(1, 4)
Also, you have to call the function with the value, not with the list as parameter. And the final trick to unzip the result into two lists, is to simply zip(*lst)
the result of the list comprehension:
xlist, ylist = zip(*[f(value) for value in x])
Now the result is as expected:
xlist
=> [2, 4, 6]
ylist
=> [1, 4, 9]
Solution 3
Use the build-in function zip()
,
def f(x):
return 2*x, x*x
x = range(1, 4)
xlist, ylist = zip(*[f(value) for value in x])
print(xlist, ylist)
# ((2, 4, 6), (1, 4, 9))
Solution 4
Use
zip(*your_list_of_bituples)
Example
demo_list = [(1, 2), (2, 3), (4, 5)]
zip(*demo_list)
Will give
[(1, 2, 4), (2, 3, 5)]
Solution 5
I know it's late but the following gets what you want.
def f(value):
xlist = []
ylist = []
for x, y in [(2*x, x*x) for x in range(value)]:
xlist.append(x)
ylist.append(y)
return xlist, ylist
x = int(input("enter a value: "))
xval, yval = f(x)
print(f"xlist = {xval}\nylist = {yval}")
Related videos on Youtube
Christophe
Updated on September 27, 2022Comments
-
Christophe over 1 year
I have a function that returns two values, and I would like use a list comprehension to fill two lists. for example:
def f(x): return 2*x,x*x x = range(3) xlist, ylist = [f(value) for value in x] EDITS from answers below: xtuple, ytuple = zip(*[f(value) for value in x]) xlist, ylist = map(list,zip(*[f(value) for value in x]))
where the expected return should be:
xlist = [0, 2, 4] ylist = [0, 1, 4]
my question boils down to:
Currently I get a list of tuples, while this is reasonable I will end up needing two independent lists. currently I could have 1 placeholder (tuple list) variable, and 3 total comprehensions. But I'm wondering if there is a clean way to do it with as single list comprehension.
Worth noting: in the real code my two returns are correlated, so I cannot simply split the function into two.
-
Christophe about 7 yearsgood call on the edit, I was generating a simple version and didn't test the simple version, I'll update the prompt.
-
Christophe about 7 yearsGood catch on he mapping too. In my case I'm iterating over the return so lists or tuples are both fine but that is good to note.