根据Python中的条件求和嵌套列表

问题描述:

我有一个看起来像这样的嵌套列表:

I have a nested list looking like this:

[['Vienna','2012', 890,503,70],['London','2014', 5400, 879,78],
 ['London','2014',4800,70,90],['Bern','2013',300,450,678], 
 ['Vienna','2013', 700,850,90], ['Bern','2013',500,700,90]]

如果城市和年份相等,我想做的就是将子列表中的每个整数值与另一个子列表求和.我首先想到的是以城市和年份为关键字的字典,但排序时出现了问题.

What I want to do is summing every integervalue in the sublist with another sublist if city and year are equal. I first thought of a dictionary with city and year as key, but it caused problems sorting it.

那我有:{('Vienna','2012'):[890,503,70],('Bern','2013'):[800,1150,768],...}

我也尝试过这样的事情:

I also tried something like this:

[sum(x) for x in zip(*list) if x[0] == x[0]],但是它当然不起作用.

[sum(x) for x in zip(*list) if x[0] == x[0]] but of course it did not work.

我可以对嵌套列表执行类似的操作,以便按城市和年份对其进行排序会更容易吗?

Can I do something like this with a nested list to so sorting it by city and year would be easier?

您可以构造一个结果dict,其中键是原始列表中前两项的元组,值是数字的list.每次将值添加到dict时,都可以使用 get 返回现有元素或给定默认值,在这种情况下为空列表.

You could construct a result dict where key is tuple of first two items in the original lists and value is list of numbers. Every time you add value to dict you could use get to either return existing element or given default value, in this case empty list.

一旦有了现有列表和要添加的列表,就可以使用 zip_longest fillvalue可以从两个列表中求和. zip_longest返回长度为2的元组,其中每个列表中包含一个数字.如果一个列表比其他fillvalue长,则默认使用该列表,因此,如果列表的长度不同,这也将起作用.最后,列表理解可以用来对每个项目求和以得到一个新值:

Once you have the existing list and list to add you can use zip_longest with fillvalue to get numbers to sum from both lists. zip_longest returns tuples of length 2 containing one number from each list. In case one list is longer than other fillvalue is used as default so this will also work in case lists have different lengths. Finally list comprehension could used to sum each item for a new value:

from itertools import zip_longest

l = [
    ['Vienna','2012', 890,503,70],['London','2014', 5400, 879,78],
    ['London','2014',4800,70,90],['Bern','2013',300,450,678],
    ['Vienna','2013', 700,850,90], ['Bern','2013',500,700,90]
]

res = {}
for x in l:
    key = tuple(x[:2])
    res[key] = [i + j for i, j in zip_longest(res.get(key, []), x[2:], fillvalue=0)]

print(res)

输出:

{('Vienna', '2013'): [700, 850, 90], ('London', '2014'): [10200, 949, 168], 
 ('Vienna', '2012'): [890, 503, 70], ('Bern', '2013'): [800, 1150, 768]}  

如果您要按字母顺序对城市进行排序,并且要最先更新年份,可以将自定义key传递给sorted:

If you want to sort the cities alphabetically and years latest first you could pass custom key to sorted:

for item in sorted(res.items(), key=lambda x: (x[0][0], -int(x[0][1]))):
    print(item)

输出:

(('Bern', '2013'), [800, 1150, 768])
(('London', '2014'), [10200, 949, 168])
(('Vienna', '2013'), [700, 850, 90])
(('Vienna', '2012'), [890, 503, 70])