识别列表列表中的重复项并总结其最后项目

时间:2014-04-07 20:10:53

标签: python list

我有一个列表列表,我希望从中删除重复项,并总结重复项'最后的元素。如果项目的前2个元素相同,则该项目是重复的。用一个例子可以更好地说明这一点:

input = [['a', 'b', 2], ['a', 'c', 1], ['a', 'b', 1]]

# Desired output
output = [['a', 'b', 3], ['a', 'c', 1]]

这里有类似的问题,但我还没有找到一个可以同时处理列表清单和汇总列表项的问题。

我尝试了几种方法,但无法使其发挥作用:

  • 创建输入列表的副本,制作嵌套循环,如果找到第二个副本,则将其最后一个项目添加到原始 - >这太麻烦了,嵌套太多了
  • 我查看了收藏柜台,但它似乎不适用于列表清单
  • itertools

你能否就如何解决这个问题给我任何指示?

5 个答案:

答案 0 :(得分:4)

我不认为列表是最好的数据结构。我会使用带有元组键的字典。我真的需要列表,你可以稍后创建一个:

from collections import defaultdict

data = [['a', 'b', 2], ['a', 'c', 1], ['a', 'b', 1]]

result = collections.defaultdict(int) # new keys are auto-added and initialized as 0
for item in data:
    a, b, value = item
    result[(a,b)] += value
print result
# defaultdict(<type 'int'>, {('a', 'b'): 3, ('a', 'c'): 1})
print dict(result)
# {('a', 'b'): 3, ('a', 'c'): 1}
print [[a, b, total] for (a, b), total in result.items()]
# [['a', 'b', 3], ['a', 'c', 1]]

答案 1 :(得分:2)

您可以使用Counter;某人已经给出了手动defaultdict解决方案;所以这里有一个itertools.groupby,只是为了变化:

>>> from itertools import groupby
>>> inp = [['a', 'b', 2], ['a', 'c', 1], ['a', 'b', 1]]
>>> [k[:2] + [sum(v[2] for v in g)] for k,g in groupby(sorted(inp), key=lambda x: x[:2])]
[['a', 'b', 3], ['a', 'c', 1]]

但我的第二个@m.wasowski认为字典(或dict子类,如defaultdict或Counter)可能是一个更好的数据结构。

使用[:-1][-1]代替[:2][2]也更为一般,但我懒得做出改变。 : - )

答案 2 :(得分:2)

我更喜欢这种方法:

>>> from collections import Counter
>>> from itertools import repeat, chain
>>> sum((Counter({tuple(i[:-1]): i[-1]}) for i in input), Counter())
Counter({('a', 'b'): 3, ('a', 'c'): 1})

(感谢@DSM指出我原来答案有所改进。)

如果你想以列表形式:

>>> [[a, b, n] for (a,b),n in _.items()]
[['a', 'b', 3], ['a', 'c', 1]]

答案 3 :(得分:1)

>>> t = [['a', 'b', 2], ['a', 'c', 1], ['a', 'b', 1]]
>>> sums = {}
>>> for i in t:
    sums[tuple(i[:-1])] = sums.get(tuple(i[:-1]),0) + i[-1]
>>> output = [[a,b,sums[(a,b)]] for a,b in sums]
>>> output
[['a', 'b', 3], ['a', 'c', 1]]

答案 4 :(得分:1)

inp = [['a', 'b', 2], ['a', 'c', 1], ['a', 'b', 1], ['a', 'c', 2], ['a', 'b', 4]]

lst = []
seen = []
for i, first in enumerate(inp):
    if i in seen:
        continue
    found = False
    count = first[-1]
    for j, second in enumerate(inp[i + 1:]):
        if first[:2] == second[:2]:
            count += second[-1]
            found = True
            seen.append(i + j + 1)
    if found:
        lst.append(first[:-1] + [count])
    else:
        lst.append(first)

print(lst)
# [['a', 'b', 7], ['a', 'c', 3]]