我想知道我是否可以使用一个列表理解来分配多个列表。我无论如何都无法理解语法。
所以,而不是......
xs = [item.km for item in data]
ys = [item.price for item in data]
我想做...
xs, ys = [km, price for km, price in data]
# or...
xs, ys = [item.km, item.price for item in data]
但这会引发语法错误,我似乎无法找到错误。
即使看起来很明显,数据如下......
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)
...
答案 0 :(得分:6)
如果我正确理解了您的结构,您需要使用带有star-argument的zip()
来转置您的数据:
xs, ys = zip(*[(km, price) for km, price in data])
答案 1 :(得分:3)
单个列表理解产生一个列表。您已尝试使用多个赋值将结构[(a,b), (a,b), (a,b)]
的列表分配给两个变量,但这不起作用,因为条目数不匹配。您可以生成对组件的列表:
kms = [item.km for item in data]
prices = [item.price for item in data]
但这会对列表data
进行两次处理。如果避免这种情况非常重要,我们可以并行构建两个列表,但这仍然不是一个单一的理解:
kms, prices = [], []
for item in data:
kms.append(item.km)
prices.append(item.price)
通过预先分配列表,您可以在内存管理器上实现更低的负载:
kms, prices = [None]*len(data), [None]*len(data)
for i,item in enumerate(data):
kms[i]=item.km
prices[i]=item.price
但最有可能的是,你最好用联合方式处理数据,比如numpy或pandas。
可以使用折叠来生成两个列表,其中包含来自一个解释的输入,但在常见的Python实现中,它既复杂又低效。
答案 2 :(得分:1)
简单的答案就像其他人已经指出的那样:列表理解产生一个列表。
但是,正如@Chris_Rands建议的那样,您可以使用zip
转置数据。我会调整它并使用生成器使其快一点。
xs, ys = zip(*((item.km, item.price) for item in data))
问题是上面会在数据集上多次迭代,以产生你期望的结果。使用普通for
迭代将表现得更好,因为Yann's answer状态(答案有更好的选择):
xs, ys = [], []
for item in data:
xs.append(item.km)
ys.append(item.price)
有时我们需要牺牲一些有利于表现的东西。在这种情况下:
zip
是一个很棒的工具,但它并不是真正意义上的。对于不知道用例的人来说,该片段不易读取,并且使用生成器也很慢(O(2 * n ^ 2)或可能 O(n ^ 2)没有经过测试)。for
将使您的代码真正更快(O(n)),这可能真的很重要,具体取决于data
的大小。