![](/img/trans.png)
[英]Python sum of second and third element of tuple in list of tuples grouped by first
[英]Python Sum Second Element of Tuple by First Element
我在 Python3 中有以下两个列表:
list1 = [(3, 2), (1, 5), (4, 2), (2, 0)]
list2 = [(1, 6), (2, 1), (3, 3), (4, 0)]
列表中的每个元组都是 (id, score) 的形式。 我想分别将每个 id 的两个列表中的分数组合起来,然后按分数降序排序。 所以,output 应该是:
list3 = [(1, 11), (3, 5), (4, 2), (2, 1)]
最简单的方法是什么?
使用groupby
按 id 分组,找到他们的分数总和并按分数降序排序:
from itertools import groupby
list1 = [(3, 2), (1, 5), (4, 2), (2, 0)]
list2 = [(1, 6), (2, 1), (3, 3), (4, 0)]
f = lambda x: x[0]
list3 = sorted([(k, sum(x[1] for x in g)) for k, g in groupby(sorted(list1 + list2, key=f), key=f)], key=lambda x: x[1], reverse=True)
# [(1, 11), (3, 5), (4, 2), (2, 1)]
没有任何外部依赖的更简单的解决方案可能是:
list1 = [(3, 2), (1, 5), (4, 2), (2, 0)]
list2 = [(1, 6), (2, 1), (3, 3), (4, 0)]
list1.sort()
list2.sort()
list3 = [(list1[i][0], list1[i][1] + list2[i][1]) for i in range(len(list1))]
list3.sort(key=lambda x: x[1], reverse=True)
print(list3)
#[(1, 11), (3, 5), (4, 2), (2, 1)]
尽管这假设了一些事情:
[0]
索引中拥有 ID,在[1]
中得分也许这对这种情况没问题? 取决于您希望它的适用范围有多广。
一种方法是将至少一个列表转换为字典:
d = dict(list2)
print(sorted(((k, v+d[k]) for k, v in list1),
key=lambda a: a[1], reverse=True))
对于更一般的情况,您可能有超过 2 个列表并且并非每个 id 都必须出现在每个列表中,这可以变成:
dicts = [dict(L) for L in [list1, list2]]
keys = set().union(*dicts) # get all of the IDs
sums = ((k, sum(d.get(k, 0) for d in dicts)) for k in keys)
print(sorted(sums, key=lambda a: a[1], reverse=True))
或更易读
sums = {}
for scores in [list1, list2]:
for id_, score in scores:`
if id_ in sums:
sums[id_] += score
else:
sums[id_] = score
print(sorted(sums, key=lambda a: a[1], reverse=True))
也许最好的选择是使用具有most_common
方法的Counter
来进行您想要的排序。
from collections import Counter
print((Counter(dict(list1)) + Counter(dict(list2))).most_common())
另一个使用dict comprehension的解决方案:
sorted({id: dict(list1).get(id, 0) + dict(list2).get(id, 0) for id in dict(list1)}.items(), reverse=True, key=lambda x: x[1])
[(1, 11), (3, 5), (4, 2), (2, 1)]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.