在列表列表中查找重复项

时间:2013-11-06 11:51:29

标签: python list python-2.7

我正在使用Python 2.7,我正在尝试重复删除列表列表并合并重复项的值。

现在我有:

original_list = [['a', 1], ['b', 1], ['a', 1], ['b', 1], ['b', 2], ['c', 2], ['b', 3]]

我希望匹配每个嵌套列表的第一个元素,然后添加第二个元素的值。我想最终得到这个(最终列表的顺序无关紧要):

ideal_output = [['a', 2], ['b', 7], ['c', 2]]

到目前为止,我有一些代码会根据每个嵌套列表的第一个元素找到重复值:

for item in original_list:
    matches = -1
    for x in original_list:
        if (item[0] == x[0]):
            matches += 1
    if matches >= 1: 
        if item[0] not in duplicates_list:
            duplicates_list.append(item[0])

从这里我需要搜索original_list中的所有duplicates_list项并添加值,但我不确定最好的方法是什么。

7 个答案:

答案 0 :(得分:30)

很多好的答案,但他们都使用了比我更多的代码,所以这是我的看法,因为它值得:

totals = {}
for k,v in original_list:
  totals[k] = totals.get(k,0) + v

# totals = {'a': 2, 'c': 2, 'b': 7}

一旦你有了这样的词典,从任何这些答案中,你可以使用items来获取元组列表:

totals.items()
# => [('a', 2), ('c', 2), ('b', 7)]

并在元组中映射list以获取列表列表:

map(list, totals.items())
# => [['a', 2], ['c', 2], ['b', 7]]

然后按顺序排序:

sorted(map(list, totals.items()))
# => [['a', 2], ['b', 7], ['c', 2]]

答案 1 :(得分:14)

>>> from collections import Counter
>>> lst = [['a', 1], ['b', 1], ['a', 1], ['b', 1], ['b', 2], ['c', 2], ['b', 3]]
>>> c = Counter(x for x, c in lst for _ in xrange(c))

Counter({'b': 7, 'a': 2, 'c': 2})

>>> map(list, c.iteritems())
[['a', 2], ['c', 2], ['b', 7]]

或者,不重复每个项目(a, b) b次(@hcwhsa):

>>> from collections import Counter
>>> lst = [['a', 1], ['b', 1], ['a', 1], ['b', 1], ['b', 2], ['c', 2], ['b', 3]]
>>> c = sum((Counter(**{k:v}) for k, v in lst), Counter())

Counter({'b': 7, 'a': 2, 'c': 2})

>>> map(list, c.iteritems())
[['a', 2], ['c', 2], ['b', 7]]

答案 2 :(得分:13)

使用collections.Counter

from collections import Counter
original_list = [['a', 1], ['b', 1], ['a', 1], ['b', 1], ['b', 2], ['c', 2], ['b', 3]]
result = Counter()
for k, v in original_list:
     result.update({k:v})

map(list, result.items())
# [['a', 2], ['c', 2], ['b', 7]]

调查结果

所以,很多答案,观点和赞成。我甚至从无到有赢得了我的第一个Nice answer(在过去的两天里,我做了很多值得更多研究和努力的答案)。鉴于此,我决定使用从头开始编写的simple script来至少完成一些研究和测试解决方案的性能。为了大小,不要直接在代码中包含代码。

每个函数都以它的作者命名,很容易找到问题。 thefourtheye的解决方案现在等于Mark Reed中的一个,并以原始形式进行评估,基于itertools.groupby解决方案的第2个状态进行评估。

每次测试几次(样本),每个样本依次调用几次函数迭代。我评估了样品时间的最小值,最大值和标准偏差。

我们开始,进行10次探测测试。

testing: thefourtheye, kroolik2, void, kroolik, alko, reed, visser
   10 samples
   10 iterations each
         author   min     avg     max    stddev
           reed 0.00000 0.00000 0.00000 0.00000
         visser 0.00000 0.00150 0.01500 0.00450
   thefourtheye 0.00000 0.00160 0.01600 0.00480
  thefourtheye2 0.00000 0.00310 0.01600 0.00620
           alko 0.00000 0.00630 0.01600 0.00772
           void 0.01500 0.01540 0.01600 0.00049
       kroolik2 0.04700 0.06430 0.07800 0.00831
        kroolik 0.32800 0.34380 0.37500 0.01716

查看底部两行:此时kroolik解决方案被取消资格,因为任何合理数量的样本*迭代将执行数小时。这是最后的测试。我手动添加了一些upvotes到ouptut:

testing: thefourtheye, kroolik2, void, kroolik, alko, reed, visser
   100 samples
  1000 iterations each
         author  upvotes   min     avg     max    stddev
           reed  [20]    0.06200 0.08174 0.15600 0.01841
   thefourtheye   [5]    0.06200 0.09971 0.20300 0.01911
         visser   [6]    0.10900 0.12392 0.23500 0.02263
  thefourtheye2          0.25000 0.29674 0.89000 0.07183
           alko  [11]    0.56200 0.62309 1.04700 0.08438
           void   [3]    1.50000 1.65480 2.39100 0.18721
        kroolik  [14]     [DSQ]

答案 3 :(得分:10)

如果订单无关紧要,您可以使用此

original_list = [['a', 1], ['b', 1], ['a', 1], ['b', 1], ['b', 2], ['c', 2], ['b', 3]]
myDict = {}
for first, second in original_list:
    myDict[first] = myDict.get(first, 0) + second
result = [[key, value] for key, value in myDict.items()]
print result

或者你可以使用groupby并且代码变成一个单一的

original_list = [['a', 1], ['b', 1], ['a', 1], ['b', 1], ['b', 2], ['c', 2], ['b', 3]]
from itertools import groupby
print [[key, sum(item[1] for item in list(group))]
       for key, group in groupby(sorted(original_list), lambda x:x[0])]

<强>输出

[['a', 2], ['b', 7], ['c', 2]]

答案 4 :(得分:5)

您可以使用collections.defaultdict

original_list = [['a', 1], ['b', 1], ['a', 1], ['b', 1], ['b', 2], ['c', 2], ['b', 3]]
import collections
data = collections.defaultdict(list)
for item in original_list:
    data[item[0]].append(item[1])

output = {key: sum(values) for key, values in data.items()}
print output
# gives: {'a': 2, 'c': 2, 'b': 7}

答案 5 :(得分:5)

我知道这很难看,但我试着用1个班轮实现它很有趣:

map(list, set(([(x[0], sum([i[1] for i in original_list if i[0]==x[0]])) for x in original_list])))

输出:

[['a', 2], ['b', 7], ['c', 2]]

答案 6 :(得分:2)

也许你也可以试试这个,

>>> x = [[1,1],[2,2],[1,1],[2,2],[3,3],[4,4],[4,4]]
>>> z = []
>>> for i in x:
>>>    if i not in z:
>>>        z.append(i)
>>>
>>> z
[[1, 1], [2, 2], [3, 3], [4, 4]]