Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple assignation with list comprehension

I am trying to know if I can assign multiple lists with one single list comprehension. I somehow can't get my mind around the syntax.

So, instead of doing...

xs = [item.km for item in data]
ys = [item.price for item in data]

I'd like to do...

xs, ys = [km, price for km, price in data]
# or...
xs, ys = [item.km, item.price for item in data]

But this throws me a syntax error, and I can't seem to find the error.

Even if it seemed obvious, the data is as follow...

for elem in data:
    print elem
# outputs (this is a namedtuple) :
# mileage(km=22899.0, price=7990.0)
# mileage(km=48235.0, price=6900.0)
# mileage(km=54000.0, price=7990.0)
# mileage(km=60949.0, price=7490.0)
...
like image 416
IMCoins Avatar asked Dec 02 '25 09:12

IMCoins


2 Answers

If I understand your structure correctly, you need zip() with the star-argument to transpose your data:

xs, ys = zip(*[(km, price) for km, price in data]) 
like image 112
Chris_Rands Avatar answered Dec 04 '25 21:12

Chris_Rands


A single list comprehension produces a single list. You've tried to assign a list of the structure [(a,b), (a,b), (a,b)] to two variables using multiple assignment, and this doesn't work because the number of entries doesn't match. You could instead produce lists of the pair components:

kms = [item.km for item in data]
prices = [item.price for item in data]

But this does process the list data twice. If it's really important to avoid this, we could build the two lists in parallel, but that still isn't a single comprehension:

kms, prices = [], []
for item in data:
    kms.append(item.km)
    prices.append(item.price)

You could achieve a lower load on the memory manager by preallocating the lists:

kms, prices = [None]*len(data), [None]*len(data)
for i,item in enumerate(data):
    kms[i]=item.km
    prices[i]=item.price

But most likely you'd be better off processing the data in a joint manner using something like numpy or pandas.

It's possible to use a fold to produce two lists with input from one comprehension, but it's both complex and inefficient in common Python implementations.

like image 22
Yann Vernier Avatar answered Dec 04 '25 23:12

Yann Vernier