【问题标题】:In Python, how do I take a list and reduce it to a list of duplicates?在 Python 中,如何获取列表并将其减少为重复列表?
【发布时间】:2009-03-26 13:01:52
【问题描述】:

我有一个应该是唯一的字符串列表。我希望能够快速检查重复项。具体来说,我希望能够获取原始列表并生成一个包含任何重复项的新列表。我不在乎这些项目重复了多少次,所以如果有两个重复项,它就不必有两个单词。

不幸的是,我想不出一种不笨重的方法来做到这一点。有什么建议吗?

编辑: 感谢您的回答,我想我会澄清一下。我不关心为了它自己而拥有一个独特的列表。我正在根据文本文件生成列表,我想知道重复项是什么,以便我可以进入文本文件并在出现时删除它们。

【问题讨论】:

    标签: python


    【解决方案1】:

    这段代码应该可以工作:

    duplicates = set()
    found = set()
    for item in source:
        if item in found:
            duplicates.add(item)
        else:
            found.add(item)
    

    【讨论】:

    • 稍后我必须确保它有效,但这符合我的想法并且看起来很干净。
    • 使用 set() 比使用列表有什么特别的优势吗? 'in' 也适用于列表?
    • @becomingGuru, set() 将防止重复添加但不排序。优点/缺点取决于您的应用程序
    • @becomingGuru:我认为 'in' 在集合中的表现要好于列表。我没有过多研究这个的实现,但我自己的基准测试验证了它。
    • 我相信集合是哈希表,这意味着包含测试平均是 O(1),而包含列表是 O(n)。
    【解决方案2】:

    来自itertoolsgroupby 可能在这里有用:

    
    from itertools import groupby
    duplicated=[k for (k,g) in groupby(sorted(l)) if len(list(g)) > 1]
    

    基本上你用它来查找多次出现的元素...

    注意。需要调用sorted,因为groupby 只有在输入排序后才能正常工作。

    【讨论】:

      【解决方案3】:

      这将在一行中创建列表:

      L = [1, 2, 3, 3, 4, 4, 4]
      L_dup = set([i for i in L if L.count(i) > 1])
      

      【讨论】:

      • 虽然很短,但这段代码有 O(N²) 的性能。对于 L 中的每个项目,将需要 L 中该项目的完整计数。也仅在 2.6 中
      • @Staale, Brian:你知道 Eugene M 正在使用的输入的典型大小,因此他需要关心性能吗?
      • 如果信息有帮助的话,实际上 N 大约是 20-50 个短字符串。
      • 当生成器表达式可以完成工作时,列表推导式的另一种多余使用。
      【解决方案4】:

      绝对不是最快的方法,但它似乎可以解决问题:

      >>> lst = [23, 32, 23, None]
      >>> set(i for i in lst if lst.count(i) > 1)
      {23}
      

      【讨论】:

      • 我喜欢这种方法!小列表的 O(n) 和 O(n*n) 应该没问题。
      【解决方案5】:

      这是一个简单的 1-liner:

      >>> l = ['a', 'a', 3, 'r', 'r', 's', 's', 2, 3, 't', 'y', 'a', 'w', 'r']
      >>> [v for i, v in enumerate(l) if l[i:].count(v) > 1 and l[:i].count(v) == 0]
      ['a', 3, 'r', 's']
      

      enumerate 返回一个索引列表,我们用它来拼接我们的输入列表,确定循环中当前索引之前是否有任何重复项以及我们是否已经在后面找到了重复项。

      【讨论】:

      • 那是可怕的代码和可怕的风格(如果您必须使用单字母名称,请保留j 作为索引;使用v 作为值)。稍微不那么可怕:[v for i, v in enumerate(L) if v not in L[i+1:] and v not in L[:i]]
      • 这是一个缓慢的 O(n^2) 复杂度类。
      • 对于极少数不可散列的混合类型的项目是可接受的,而其他解决方案是不可能的。 (混合元组、字符串、unicode 和一些不可散列的)
      【解决方案6】:

      如果你不关心重复的顺序:

      a = [1, 2, 3, 4, 5, 4, 6, 4, 7, 8, 8]
      b = sorted(a)
      duplicates = set([x for x, y in zip(b[:-1], b[1:]) if x == y])
      

      【讨论】:

        【解决方案7】:

        就个人而言,我认为这是实现 O(n) 性能的最简单方法。类似于 vartec 的解决方案,但不需要 import,也无需担心 Python 版本依赖:

        def getDuplicates(iterable):
            d = {}
            for i in iterable:
                d[i] = d.get(i, 0) + 1
            return [i for i in d if d[i] > 1]
        

        【讨论】:

          【解决方案8】:

          基于 'set' 的解决方案有一个小缺点,即它们仅适用于可散列对象。

          另一方面,基于 itertools.groupby 的解决方案适用于所有可比较的对象(例如:字典和列表)。

          【讨论】:

            【解决方案9】:

            编辑:好的,因为你只想要重复,所以不起作用。

            使用 python > 2.4 :

            你已经设置好了,做吧:

            my_filtered_list = list(set(mylist))
            

            Set 是一种本质上没有重复的数据结构。

            对于较旧的 Python 版本:

            my_filtered_list = list(dict.fromkeys(mylist).keys())
            

            字典将唯一键映射到值。我们使用“唯一”特征来消除重复。

            【讨论】:

              猜你喜欢
              • 2020-09-03
              • 2014-12-14
              • 2016-09-29
              • 2017-11-10
              • 2019-08-08
              • 2015-09-17
              • 1970-01-01
              • 2013-09-15
              • 1970-01-01
              相关资源
              最近更新 更多