【问题标题】:python remove duplicates from 2 listspython从2个列表中删除重复项
【发布时间】:2013-08-14 05:39:05
【问题描述】:

我正在尝试从 2 个列表中删除重复项。所以我写了这个函数:

a = ["abc", "def", "ijk", "lmn", "opq", "rst", "xyz"]

b = ["ijk", "lmn", "opq", "rst", "123", "456", ]

for i in b:
    if i in a:
        print "found " + i
        b.remove(i)

print b

但我发现匹配项后面的匹配项没有被删除。

我得到这样的结果:

found ijk
found opq
['lmn', 'rst', '123', '456']

但我希望得到这样的结果:

['123', '456']

我怎样才能修复我的功能来做我想做的事?

谢谢。

【问题讨论】:

    标签: python list duplicate-removal


    【解决方案1】:

    您的问题似乎是您正在更改您正在迭代的列表。而是迭代列表的副本。

    for i in b[:]:
        if i in a:
            b.remove(i)
    
    
    >>> b
    ['123', '456']
    

    但是,使用列表推导式怎么样?

    >>> a = ["abc", "def", "ijk", "lmn", "opq", "rst", "xyz"]
    >>> b = ["ijk", "lmn", "opq", "rst", "123", "456", ]
    >>> [elem for elem in b if elem not in a ]
    ['123', '456']
    

    【讨论】:

    • 如果a 列表变得更长,那么将其转换为set 可能会更有效(x in s 对于集合来说是 O(1),对于集合来说是 O(n)列表)根据wiki.python.org/moin/TimeComplexity
    【解决方案2】:

    或一组

    set(b).difference(a)
    

    如果这很重要,预先警告的集合将不会保持秩序

    【讨论】:

      【解决方案3】:

      怎么样

      b= set(b) - set(a)
      

      如果您需要在 b 中可能出现重复,以便在结果和/或要保留的顺序中出现重复,那么

      b= [ x for x in b if not x in a ] 
      

      会的。

      【讨论】:

      • 这个答案被否决了一次。谁能告诉我为什么?任何严重的语法/概念错误?对所提出的问题没有贡献(并考虑到有时很难理解所提出的问题)?英语不好到难以理解的地步?
      • 我看到if not x in a,对我来说有点奇怪。它也很好用,但我认为您应该将其更改为if x not in a 将使代码更清晰。我的个人意见。
      • 注意这里的列表理解选项必须写成:[x for x in d if not (x in o )]才能通过pep8。
      【解决方案4】:

      您要求删除两个重复的列表,这是我的解决方案:

      from collections import OrderedDict
      a = ["abc", "def", "ijk", "lmn", "opq", "rst", "xyz"]
      b = ["ijk", "lmn", "opq", "rst", "123", "456", ]
      
      x = OrderedDict.fromkeys(a)
      y = OrderedDict.fromkeys(b)
      
      for k in x:
          if k in y:
              x.pop(k)
              y.pop(k)
      
      
      print x.keys()
      print y.keys()
      

      结果:

      ['abc', 'def', 'xyz']
      ['123', '456']
      

      这里的好处是您可以保持两个列表项的顺序

      【讨论】:

        【解决方案5】:

        这就是正在发生的事情。假设你有这个列表:

        ['a', 'b', 'c', 'd']
        

        并且您正在遍历列表中的每个元素。假设您当前位于索引位置 1:

        ['a', 'b', 'c', 'd']
               ^
               |
           index = 1
        

        ...然后您删除索引位置 1 处的元素,为您提供:

        ['a',      'c', 'd']
               ^
               |
            index 1
        

        删除项目后,其他项目向左滑动,给你这个:

        ['a', 'c', 'd']
               ^
               |
            index 1
        

        然后当循环再次运行时,循环将索引增加到 2,给你这个:

        ['a', 'c', 'd']
                    ^ 
                    |
                 index = 2
        

        看看你是如何跳过“c”的?教训是:永远不要从你正在循环的列表中删除一个元素。

        【讨论】:

          【解决方案6】:

          在迭代列表时避免编辑列表问题的一种方法是使用推导:

          a = ["abc", "def", "ijk", "lmn", "opq", "rst", "xyz"]
          b = ["ijk", "lmn", "opq", "rst", "123", "456", ]
          b = [x for x in b if not x in a]
          

          【讨论】:

          • Mario Rossi 和 Sukrit Kalra 1 小时前发布的相同解决方案。
          • 也许@Mayur Patel 和我同时开始写它。这是元的主题(我猜):要么在 1(或可能 2)人回答问题时阻止问题(在一定时间内?),或者至少表明有多少其他人在回答问题。我的意思是在答案发布之前。不过,我是个菜鸟。如果已经有类似的东西,请告诉我。
          【解决方案7】:

          已经有很多关于“你如何修复它?”的答案,所以这是一个“你如何改进它并变得更加pythonic?”:因为你想要实现的是获得列表@987654322之间的区别@ 和列表a,你应该在集合上使用差异操作(operations on sets):

          >>> a = ["abc", "def", "ijk", "lmn", "opq", "rst", "xyz"]
          >>> b = ["ijk", "lmn", "opq", "rst", "123", "456", ]
          >>> s1 = set(a)
          >>> s2 = set(b)
          >>> s2 - s1
          set(['123', '456'])
          

          【讨论】:

            【解决方案8】:

            您可以使用 lambda 函数。

            f = lambda list1, list2: list(filter(lambda element: element not in list2, list1))
            

            list2 中的重复元素从 list1 中删除。

            >>> a = ["abc", "def", "ijk", "lmn", "opq", "rst", "xyz"]
            >>> b = ["ijk", "lmn", "opq", "rst", "123", "456"]
            >>> f(a, b)
            ['abc', 'def', 'xyz']
            >>> f(b, a)
            ['123', '456']
            

            【讨论】:

              【解决方案9】:

              按照 7stud 的思路,如果你倒序遍历列表,你就没有遇到你遇到的问题:

              a = ["abc", "def", "ijk", "lmn", "opq", "rst", "xyz"]
              
              b = ["ijk", "lmn", "opq", "rst", "123", "456", ]
              
              for i in reversed(b):
                  if i in a:
                      print "found " + i
                      b.remove(i)
              
              print b
              
              Output:
              found rst
              found opq
              found lmn
              found ijk
              ['123', '456']
              
              

              【讨论】:

                【解决方案10】:

                一个简单的解决方法是遍历一个范围,查看索引处的元素,删除该元素,然后将计数器减 1。
                模拟未经测试的代码

                for i in range(0, len(b)):
                    if b[i] in a:
                        del b[i]
                        i -= 1
                
                

                【讨论】:

                • 删除您正在迭代的可迭代对象的元素通常会导致问题。当您使用提供的示例列表运行此代码时会发生什么?
                • 请添加更多详细信息以扩展您的答案,例如工作代码或文档引用。
                【解决方案11】:

                你可以使用综合列表

                a = ["abc", "def", "ijk", "lmn", "opq", "rst", "xyz"]
                b = ["ijk", "lmn", "opq", "rst", "123", "456", ]
                

                从 a 中删除的重复值

                c=[value for value in a if value not in b]
                

                从 b 中删除重复值

                c=[value for value in b if value not in a]
                

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 2020-05-20
                  • 2011-09-29
                  • 2013-08-03
                  • 2020-08-04
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多