简体   繁体   English

列表理解的多重分配

[英]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)
...

如果我正确理解您的结构,则需要带星号的zip()来转置数据:

xs, ys = zip(*[(km, price) for km, price in data]) 

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. 您尝试使用多重分配将结构[(a,b), (a,b), (a,b)]分配给两个变量,但这不起作用,因为条目数不匹配。 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. 但这确实会两次处理列表data 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. 但是最有可能的情况是,最好使用numpy或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. 可以使用fold来产生两个列表,并从一个理解中获得输入,但是在常见的Python实现中既复杂又效率低下。

Simple answer is, like others have pointed already: a list comprehension produces a single list . 就像其他人已经指出的那样,简单的答案是: 列表理解产生单个列表

You could, however, as @Chris_Rands suggested, transpose your data using zip . 但是,您可以按照@Chris_Rands的建议,使用zip转换数据。 I would tweak it and use a generator to make it a little faster. 我会对其进行调整,并使用生成器使其更快一些。

xs, ys = zip(*((item.km, item.price) for item in data))

The problem is that the above will iterate multiple times over the data set in order to produce what you expect. 问题在于,上面的代码将对数据集进行多次迭代,以产生所需的结果。 Using a plain for iteration will perform far better, as Yann's answer states (that answer has an even better alternative): 由于Yann的答案指出(使用答案甚至更好),因此使用平原for迭代的效果要好得多:

xs, ys = [], []
for item in data:
    xs.append(item.km)
    ys.append(item.price)

Sometimes we need to sacrifice some things in favour of performance. 有时我们需要牺牲一些东西来提高性能。 And in this case: 在这种情况下:

  • zip is an great tool, but it isn't exactly meant for that. zip是一个很棒的工具,但它并不完全适用于此。 That snippet isn't easily readable for people unaware of the use case, and is also slow (O(2*n^2) or maybe O(n^2) with a generator, I haven't tested). 这片段是不是人们不知道用例的简单易读,而且也慢(O(2 * N ^ 2)或可能为O(n ^ 2)与发电机,我还没有测试)。
  • Using a plain for will make your code really faster (O(n)), which may really matter depending on the size of data . 使用plain for将使您的代码真正更快(O(n)),这取决于data的大小可能真的很重要。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM