【问题标题】:Deleting repeats in a list python [duplicate]删除列表python中的重复项[重复]
【发布时间】:2011-10-04 20:52:09
【问题描述】:

可能的重复:
How do you remove duplicates from a list in Python whilst preserving order?
In Python, what is the fastest algorithm for removing duplicates from a list so that all elements are unique while preserving order?

我想知道是否有一个函数可以执行以下操作:

将列表作为参数:

list = [ 3 , 5 , 6 , 4 , 6 , 2 , 7 , 6 , 5 , 3 ]

并删除列表中的所有重复以获得:

list = [ 3 , 5 , 6 , 4 , 2 , 7 ]

我知道您可以将其转换为字典并使用字典不能重复的事实,但我想知道是否有更好的方法。

谢谢

【问题讨论】:

  • 你关心元素的顺序吗?

标签: python list


【解决方案1】:

请参阅Python documentation 了解实现此目的的三种方法。以下是从该站点复制的。将示例“mylist”替换为您的变量名称(“list”)。

第一个示例:如果您不介意重新排序列表,请将其排序,然后从列表末尾扫描,同时删除重复项:

if mylist:
    mylist.sort()
    last = mylist[-1]
    for i in range(len(mylist)-2, -1, -1):
        if last == mylist[i]:
            del mylist[i]
        else:
            last = mylist[i]

第二个例子:如果列表的所有元素都可以用作字典键(即它们都是可散列的),这通常更快:

d = {}
for x in mylist:
    d[x] = 1
mylist = list(d.keys())

第三个示例:在 Python 2.5 及更高版本中:

mylist = list(set(mylist))

【讨论】:

    【解决方案2】:

    尽管您说您不一定要使用 dict,但我认为 OrderedDict 在这里是一个干净的解决方案。

    from collections import OrderedDict
    
    l = [3 ,5 ,6 ,4 ,6 ,2 ,7 ,6 ,5 ,3]
    OrderedDict.fromkeys(l).keys()
    # [3, 5, 6, 4, 2, 7]
    

    请注意,这会保留原始顺序。

    【讨论】:

      【解决方案3】:

      list(set(l)) 不会保留订单。如果您想保留订单,请执行以下操作:

      s = set()
      result = []
      for item in l:
          if item not in s:
              s.add(item)
              result.append(item)
      
      print result
      

      这将在 O(n) 中运行,其中 n 是原始列表的长度。

      【讨论】:

        【解决方案4】:

        list(set(list)) 工作得很好。

        【讨论】:

        • 如果“罚款”的意思是“我不关心原始订单”,那么可以。
        【解决方案5】:

        首先,不要将其命名为 list ,因为这会影响内置类型列表。说,my_list

        为解决你的问题,我最常看到的方式是list(set(my_list))

        set 是一个无序容器,只有唯一元素,并且(我认为)O(1) 插入和检查成员身份

        【讨论】:

          【解决方案6】:

          在撰写此答案时,唯一保留顺序的解决方案是 OrderedDict 解决方案,以及 Dave 稍微更详细的解决方案。

          这是我们在迭代时滥用副作用的另一种方式,这也比 OrderedDict 解决方案更冗长:

          def uniques(iterable):
              seen = set()
              sideeffect = lambda _: True
              return [x for x in iterable 
                      if (not x in seen) and sideeffect(seen.add(x))]
          

          【讨论】:

            【解决方案7】:

            集合将是比 O 复杂度的字典术语更好的方法。但是这两种方法都会使您失去排序(除非您使用有序字典,否则会再次增加复杂性)。

            正如其他海报已经说过的那样,设置解决方案并不难:

            l = [ 3 , 5 , 6 , 4 , 6 , 2 , 7 , 6 , 5 , 3 ]
            list(set(l))
            

            保持顺序的一种方法是:

            def uniques(l):
                seen = set()
            
                for i in l:
                    if i not in seen:
                        seen.add(i)
                        yield i
            

            或者,以一种不太可读的方式:

            def uniques(l):
                seen = set()
                return (seen.add(i) or i for i in l if i not in seen)
            

            然后你可以像这样使用它:

            l = [ 3 , 5 , 6 , 4 , 6 , 2 , 7 , 6 , 5 , 3 ]
            list(uniques(l))
            >>> [3, 5, 6, 4, 2, 7]
            

            【讨论】:

              【解决方案8】:

              这是我自己的方便 Python 工具集合中的一个 sn-p - 它使用了 ninjagecko 在他的回答中的“滥用副作用”方法。这也很难处理非散列值,并返回与传入相同类型的序列:

              def unique(seq, keepstr=True):
                  """Function to keep only the unique values supplied in a given 
                     sequence, preserving original order."""
              
                  # determine what type of return sequence to construct
                  if isinstance(seq, (list,tuple)):
                      returnType = type(seq)
                  elif isinstance(seq, basestring):
                      returnType = (list, type(seq)('').join)[bool(keepstr)] 
                  else:
                      # - generators and their ilk should just return a list
                      returnType = list
              
                  try:
                      seen = set()
                      return returnType(item for item in seq if not (item in seen or seen.add(item)))
                  except TypeError:
                      # sequence items are not of a hashable type, can't use a set for uniqueness
                      seen = []
                      return returnType(item for item in seq if not (item in seen or seen.append(item)))
              

              这里有各种调用,有各种类型的序列/迭代器/生成器:

              from itertools import chain
              print unique("ABC")
              print unique(list("ABABBAC"))
              print unique(range(10))
              print unique(chain(reversed(range(5)), range(7)))
              print unique(chain(reversed(xrange(5)), xrange(7)))
              print unique(i for i in chain(reversed(xrange(5)), xrange(7)) if i % 2)
              

              打印:

              ABC
              ['A', 'B', 'C']
              [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
              [4, 3, 2, 1, 0, 5, 6]
              [4, 3, 2, 1, 0, 5, 6]
              [3, 1, 5]
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2014-09-30
                相关资源
                最近更新 更多