8

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

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

4 回答 4

14

使用字典获取结果:

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

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

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

于 2012-07-25T16:08:37.123 回答
4

使用默认字典:

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
于 2012-07-25T16:12:06.710 回答
2

使用 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返回合并列表的元素,按元组的第一个元素分组,因此它只是将它们相加并将其放入合并列表中。

于 2012-07-25T16:10:08.010 回答
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()返回一个包含一组键的可迭代对象,用于连接列表
sum(...)需要 'k' 再次循环通过连接列表并添加元组项 'v' 其中 k == x

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

于 2012-07-26T16:23:55.427 回答