Python最简单的方法来汇总列表元组列表的交集

时间:2012-07-25 16:03:20

标签: python list set intersection

假设我有以下两个元组列表

myList = [(1, 7), (3, 3), (5, 9)]
otherList = [(2, 4), (3, 5), (5, 2), (7, 8)]

returns => [(1, 7), (2, 4), (3, 8), (5, 11), (7, 8)]

我想设计一个合并操作,通过检查元组的第一个元素上的任何交集来合并这两个列表,如果有交叉点,则添加每个元组的第二个元素(合并两个)。在操作之后,我想根据第一个元素进行排序。

我也发布了这个,因为我认为它是一个非常普遍的问题,有一个明显的解决方案,但我觉得这个问题可能有非常pythonic的解决方案;)

4 个答案:

答案 0 :(得分:14)

使用字典作为结果:

result = {}
for k, v in my_list + other_list:
    result[k] = result.get(k, 0) + v

如果您想要一个元组列表,可以通过result.items()获取。结果列表将按任意顺序排列,但当然您可以根据需要对其进行排序。

(请注意,我重命名了您的列表以符合Python的样式约定。)

答案 1 :(得分:4)

使用defaultdict:

from collections import defaultdict
results_dict = defaultdict(int)
results_dict.update(my_list)
for a, b in other_list:
    results_dict[a] += b
results = sorted(results_dict.items())

注意:排序序列时,sorted按序列中的第一项排序。如果第一个元素相同,则它比较第二个元素。您可以使用sorted关键字参数为key一个函数排序:

results = sorted(results_dict.items(), key=lambda x: x[1]) #sort by the 2nd item

results = sorted(results_dict.items(), key=lambda x: abs(x[0])) #sort by absolute value

答案 2 :(得分:1)

使用itertools的方法:

>>> myList = [(1, 7), (3, 3), (5, 9)]
>>> otherList = [(2, 4), (3, 5), (5, 2), (7, 8)]

>>> import itertools
>>> merged = []
>>> for k, g in itertools.groupby(sorted(myList + otherList), lambda e: e[0]):
...    merged.append((k, sum(e[1] for e in g)))
... 
>>> merged
[(1, 7), (2, 4), (3, 8), (5, 11), (7, 8)]

首先将两个列表连接在一起并对其进行排序。 itertools.groupby返回合并列表的元素,按元组的第一个元素分组,因此它只是将它们相加并将其放入合并列表中。

答案 3 :(得分:0)

>>> [(k, sum(v for x,v in myList + otherList if k == x)) for k in dict(myList + otherList).keys()]
[(1, 7), (2, 4), (3, 8), (5, 11), (7, 8)]
>>>

测试了Python2.7和3.2 dict(myList + otherList).keys()返回一个包含连接列表的一组键的iterable
sum(...)使'k'再次循环通过连接列表并添加元组项'v',其中k == x

...但额外的循环增加了处理开销。使用Sven Marnach提出的显式字典可以避免它。