【问题标题】:Count the duplicates in a list of tuples计算元组列表中的重复项
【发布时间】:2015-07-03 13:05:55
【问题描述】:

我有一个元组列表:a = [(1,2),(1,4),(1,2),(6,7),(2,9)] 我想检查每个元组的单个元素是否与另一个元组中的相同位置/元素匹配,以及这种情况发生了多少次。

例如:如果某些元组中只有第一个元素有重复项,则返回元组及其重复次数。 我可以用以下代码做到这一点:

a = [(1,2), (1,4), (1,2), (6,7), (2,9)]

coll_list = []
for t in a:
    coll_cnt = 0
    for b in a:
        if b[0] == t[0]:
            coll_cnt = coll_cnt + 1
    print "%s,%d" %(t,coll_cnt)
    coll_list.append((t,coll_cnt))

print coll_list

我想知道是否有更有效的方法来做到这一点?

【问题讨论】:

  • collections.Counter(a) 会给你计数。
  • 如果你的代码可以运行,但你想改进它,你可以在这里发布:codereview.stackexchange.com
  • 您可能希望显示预期的输出,因为下面的许多答案似乎都是关于查找重复的元组而不是元组中的重复值。

标签: python list tuples


【解决方案1】:

您可以使用Counter

from collections import Counter
a = [(1,2),(1,4),(1,2),(6,7),(2,9)]
counter=Counter(a)
print counter

这将输出:

Counter({(1, 2): 2, (6, 7): 1, (2, 9): 1, (1, 4): 1})

它是一个类似于字典的对象,其中项(在本例中为元组)作为键,值包含该键被看到的次数。您的 (1,2) 元组被看到两次,而所有其他人只被看到一次。

>>> counter[(1,2)]
2

如果您对元组的每个单独部分感兴趣,您可以对元组中的每个元素使用相同的逻辑。

first_element = Counter([x for (x,y) in a])
second_element = Counter([y for (x,y) in a])

first_elementsecond_element 现在包含一个 Counter,表示在元组中每个元素看到值的次数

>>> first_element
Counter({1: 3, 2: 1, 6: 1})
>>> second_element
Counter({2: 2, 9: 1, 4: 1, 7: 1})

同样,这些是字典类对象,因此您可以直接检查特定值出现的频率:

>>> first_element[2]
1

在元组列表的第一个元素中,值 2 出现了 1 次。

【讨论】:

  • OP 不想要每个元组的出现次数。
【解决方案2】:

你可以制作count_map,并将每个元组的计数作为值存储。

>>> count_map = {}
>>> for t in a:
...     count_map[t] = count_map.get(t, 0)  +1
... 
>>> count_map
{(1, 2): 2, (6, 7): 1, (2, 9): 1, (1, 4): 1}

【讨论】:

  • 你也可以使用collections.defaultdict(int)来避免尴尬的get
  • OP 不想要每个元组的出现次数。
  • @doru OP 的代码另有说明。他/她已经一一计算了所有元组的计数,使其成为 N^2 操作。
  • @Sudipta 你有没有运行 OP 代码来查看想要的结果是什么?
  • @doru- 是的,我已经做到了。 OP 代码用于检查if only the 1st part of all tuples of the list has a dublicate。但是现在 OP 需要一个代码才能找到:if one of the elements of each tuple has a dublicate and how many times.
【解决方案3】:

使用收藏库。在以下代码 val_1 中,val_2 分别为您提供了元组的每个第一个元素和第二个元素的副本。

import collections
val_1=collections.Counter([x for (x,y) in a])
val_2=collections.Counter([y for (x,y) in a])

>>> print val_1
<<< Counter({1: 3, 2: 1, 6: 1})

这是每个元组的第一个元素的出现次数

>>> print val_2
<<< Counter({2: 2, 9: 1, 4: 1, 7: 1})

这是每个元组的第二个元素出现的次数

【讨论】:

    【解决方案4】:

    使用 pandas 这很简单而且非常快:

    import pandas
    print(pandas.Series(data=[(1,2),(1,4),(1,2),(6,7),(2,9)]).value_counts())
    
    (1, 2)    2
    (1, 4)    1
    (6, 7)    1
    (2, 9)    1
    dtype: int64
    

    【讨论】:

    • OP 不想要每个元组的出现次数。
    【解决方案5】:

    也许字典可以更好地工作。因为在您的代码中,您在列表中旅行了两次。这使得您的代码的complexity 为 O(n^2)。这不是一件好事:)

    最好的方法是一次遍历,每次遍历使用 1 或 2 个条件。这是我针对此类问题的第一个解决方案。

    a = [(1,2),(1,4),(1,2),(6,7),(2,9)]
    
    dict = {}
    for (i,j) in a:
        if dict.has_key(i):
                dict[i] += 1
        else:
                dict[i] = 1
    
    print dict
    

    对于这段代码,这将给出输出:

    {1: 3, 2: 1, 6: 1}
    

    希望对你有所帮助。

    【讨论】:

    • 您可以使用collections.defaultdict(int) 稍微清理一下循环内部
    • 是的,这很清楚。但是如果我使用集合,为什么要尝试循环,对吗? :) 我更喜欢安迪的解决方案;)
    猜你喜欢
    • 2021-06-03
    • 1970-01-01
    • 2020-06-04
    • 1970-01-01
    • 2023-03-11
    • 2019-02-04
    • 2011-05-07
    • 2018-05-30
    • 1970-01-01
    相关资源
    最近更新 更多