【问题标题】:Removing elements that have consecutive duplicates删除具有连续重复项的元素
【发布时间】:2023-01-02 21:45:23
【问题描述】:

我很好奇这个问题:Eliminate consecutive duplicates of list elements,以及它应该如何在 Python 中实现。

我想到的是:

list = [1,1,1,1,1,1,2,3,4,4,5,1,2]
i = 0

while i < len(list)-1:
    if list[i] == list[i+1]:
        del list[i]
    else:
        i = i+1

输出:

[1, 2, 3, 4, 5, 1, 2]

我想没关系。

所以我很好奇,想看看我是否可以删除元素有连续的重复并得到这个输出:

[2, 3, 5, 1, 2]

为此,我这样做了:

list = [1,1,1,1,1,1,2,3,4,4,5,1,2]
i = 0
dupe = False

while i < len(list)-1:
    if list[i] == list[i+1]:
        del list[i]
        dupe = True
    elif dupe:
        del list[i]
        dupe = False
    else:
        i += 1

但它看起来有点笨拙而不是 pythonic,你有没有更聪明/更优雅/更有效的方法来实现这个?

【问题讨论】:

标签: python list duplicates


【解决方案1】:
>>> L = [1,1,1,1,1,1,2,3,4,4,5,1,2]
>>> from itertools import groupby
>>> [key for key, _group in groupby(L)]
[1, 2, 3, 4, 5, 1, 2]

对于第二部分

>>> [k for k, g in groupby(L) if len(list(g)) < 2]
[2, 3, 5, 1, 2]

如果您不想创建临时列表只是为了获取长度,则可以在生成器表达式上使用 sum

>>> [k for k, g in groupby(L) if sum(1 for i in g) < 2]
[2, 3, 5, 1, 2]

【讨论】:

  • 请注意,docs 声明“可迭代对象已经排序”,此处的输入数据并非如此。不过,建议的解决方案对于我测试过的案例来说效果很好。
  • @normanius,要删除所有重复项,需要对输入进行排序。这个问题只是关于删除连续的重复项,所以在这种情况下你不想排序。
  • sum(1 for i in y) &lt; 2 仍然有些浪费,查看每个组元素并对可能的许多 1 求和。 all(0 for _ in y for _ in y) 最多只查看两个组元素。另外我认为它更有趣:-)
  • @Kelly 另一个想法,比嵌套的想法更明确:len(tuple(islice(g, 2))) &lt; 2。 IDK 如果它的表现会有所不同。
  • @wjandrea 对于short groups 和 ... 似乎稍微快一点
【解决方案2】:

纯 Python 中的 Oneliner

[v for i, v in enumerate(your_list) if i == 0 or v != your_list[i-1]]

【讨论】:

    【解决方案3】:

    如果你使用 Python 3.8+,你可以使用赋值表达式:=

    list1 = [1, 2, 3, 3, 4, 3, 5, 5]
    
    prev = object()
    list1 = [prev:=v for v in list1 if prev!=v]
    
    print(list1)
    

    印刷:

    [1, 2, 3, 4, 3, 5]
    

    【讨论】:

      【解决方案4】:

      一种“懒惰”的方法是使用itertools.groupby

      import itertools
      
      list1 = [1, 2, 3, 3, 4, 3, 5, 5]
      list1 = [g for g, _ in itertools.groupby(list1)]
      print(list1)
      

      产出

      [1, 2, 3, 4, 3, 5]
      

      【讨论】:

        【解决方案5】:

        您可以使用zip_longest() + 列表推导来做到这一点。

        from itertools import zip_longest 
        list1 = [1, 2, 3, 3, 4, 3, 5, 5].
             # using zip_longest()+ list comprehension       
             res = [i for i, j in zip_longest(list1, list1[1:]) 
                                                                    if i != j] 
                print ("List after removing consecutive duplicates : " +  str(res)) 
        

        【讨论】:

          【解决方案6】:

          这是一个不依赖外部包的解决方案:

          list = [1,1,1,1,1,1,2,3,4,4,5,1,2] 
          L = list + [999]  # append a unique dummy element to properly handle -1 index
          [l for i, l in enumerate(L) if l != L[i - 1]][:-1] # drop the dummy element
          

          然后我注意到 Ulf Aslak 的类似解决方案更干净:)

          【讨论】:

            【解决方案7】:

            消除列表元素的连续重复;作为替代方案,您可以使用itertools.zip_longest()列表理解作为:

            >>> from itertools import zip_longest
            
            >>> my_list = [1,1,1,1,1,1,2,3,4,4,5,1,2]
            >>> [i for i, j in zip_longest(my_list, my_list[1:]) if i!=j]
            [1, 2, 3, 4, 5, 1, 2]
            

            【讨论】:

              【解决方案8】:

              上面有很多更好/更多 pythonic 的答案,但是也可以使用 list.pop() 完成此任务:

              my_list = [1, 2, 3, 3, 4, 3, 5, 5]
              for x in my_list[:-1]:
                  next_index = my_list.index(x) + 1
                  if my_list[next_index] == x:
                      my_list.pop(next_index)
              

              产出

              [1, 2, 3, 4, 3, 5]
              

              【讨论】:

                【解决方案9】:

                另一种可能的单行代码,使用functools.reduce(不包括导入)——缺点是字符串和列表需要稍微不同的实现:

                >>> from functools import reduce
                
                >>> reduce(lambda a, b: a if a[-1:] == [b] else a + [b], [1,1,2,3,4,4,5,1,2], [])
                [1, 2, 3, 4, 5, 1, 2]
                
                >>> reduce(lambda a, b: a if a[-1:] == b else a+b, 'aa  bbb cc')
                'a b c'
                

                【讨论】:

                  猜你喜欢
                  • 2011-08-09
                  • 1970-01-01
                  • 1970-01-01
                  • 2014-03-31
                  • 2012-10-09
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多