【问题标题】:removing duplicates in list without sorting [duplicate]删除列表中的重复项而不排序[重复]
【发布时间】:2021-02-25 02:11:12
【问题描述】:

我正在尝试编写一个函数来删除列表中的重复项而不进行排序,但是在大列表中需要很长时间,有没有比这更快的方法?

from time import time

def delrepeat(rlist):
    ti = time()
    repeated = []
    for i in list(set(rlist)):
        rc = rlist.count(i)
        if rc > 1:
            repeated.append((i, rc))
    newlist = list(reversed(rlist))
    for repeat in repeated:
        i, rc = repeat
        while rc > 1:
            newlist.pop(newlist.index(i))
            rc -= 1
    print(time()-ti)
    return list(reversed(newlist))

delrepeat([3,2,1,3,5,3]*10000)
    
# --------------------------
# 5.181169271469116
# [3, 2, 1, 5]

【问题讨论】:

  • 如果您不需要订购,set() 将删除重复项。所以你可以做list(set())
  • 如果你需要维护秩序,你可以创建一个字典来保存你已经看过的元素。
  • @HunterMcMillen 不需要字典,一套就足够了。
  • @MichaelButscher 正如 at80 已经提到的那样,具有集合的解决方案 不会 保留初始顺序。这就是为什么我在我的声明前加上“如果你需要维持秩序”
  • @HunterMcMillen 我认为他们的意思是你只需要一个集合来存储看到的元素。

标签: python list algorithm duplicates


【解决方案1】:

从 Python 3.7 开始,字典是插入排序的,因此您可以非常轻松有效地从列表中删除重复项,而无需通过将其转换为 dict 并返回来更改列表的顺序

list_with_duplicates = [3, 2, 1, 3, 5, 3]
dict_from_list = {i : 0 for i in list_with_duplicates}
list_without_duplicates = list(dict_from_list.keys())

或者作为单行:

list_without_duplicates = list(dict(zip(list_with_duplicates, list_with_duplicates)))

【讨论】:

    【解决方案2】:

    如果你想在消除重复的同时保持列表的顺序,你可以使用一个跟踪已经看到的元素的集合:

    from time import time
    
    def delrepeat(rlist):
        ti = time()
        seen = set()
        res = []
        for elt in rlist:
            if elt in seen:    # check if we've seen that one, and skip if we did
                continue
            seen.add(elt)      # if not, mark it as seen, and add it to the result
            res.append(elt)
        print(time()-ti)
        return res
    
    delrepeat([3,2,1,3,5,3]*10000)
    

    在我的系统上给出这些结果:

    0.0037832260131835938
    [3, 2, 1, 5]
    

    与您的代码所需的时间相比:

    15.060174226760864
    [3, 2, 1, 5]
    

    【讨论】:

      【解决方案3】:

      您的函数看起来是二次时间。它可以在平均线性时间内完成:

      def delrepeat(l):
          seen = set()
          out = list()
          for elem in l:
              if elem not in seen:
                  out.append(elem)
                  seen.add(elem)
          return out
      

      您可以跟踪已在哈希表中看到的元素,该哈希表可以在 O(1) 时间内进行查找和添加。

      【讨论】:

      • 您的算法和您声称的二次算法是相同的。当您使用if 语句时,它使用“继续”来跳过重复项。我看不出其他区别。
      • @FrankYellin 我在谈论 OP 的代码。 for i in list(set(rlist)): rc = rlist.count(i) 在我看来是二次方。
      • 对不起。我误会了。
      猜你喜欢
      • 2012-07-16
      • 1970-01-01
      • 2018-01-26
      • 1970-01-01
      • 2010-11-22
      • 2021-12-31
      • 1970-01-01
      • 2014-09-30
      • 2013-12-03
      相关资源
      最近更新 更多