【问题标题】:Python: Identifying and deleting duplicate sequences in listPython:识别和删除列表中的重复序列
【发布时间】:2018-09-24 18:56:41
【问题描述】:

我正在寻找在列表中查找重复序列的最佳方法。 一个序列被定义为至少两个相邻的值。

示例:在以下列表中,应识别并删除重复序列。

a = [45874,
    35195, # <-
    28965,
    05867,
    25847, # <-
    94937,
    64894,
    55535,
    62899,
    00391,
    35195, # Duplicate Sequence Start
    28965,
    05867,
    25847, # Duplicate Sequence End
    08483,
    55801,
    33129,
    42616]

我无法理解任何解决方案,因此非常感谢任何帮助!

【问题讨论】:

  • 你尝试了什么?
  • 那么重叠的重复序列呢?整件事会被删除还是只有一个
  • 例如 [1, 2, 2, 3, 1, 2, 3]。它应该产生 [1, 2, 2, 3] 还是 [1, 2, 2, 3, 3]
  • 这些也是字符串吗?因为你不能输入以 0 开头的 int。
  • 感觉bisect这个模块有什么可做的……你有没有想过?我正在尝试想出一些东西,但确实很棘手......

标签: python list sequences subsequence


【解决方案1】:

在长度为 n 的字符串中找到长度为 m 的单个子序列可以用 @ 在不少于 O(nm) 的时间内完成987654321@。查找所有重复的子序列很可能不止于此。虽然,如果您只想删除子序列而不找到它们,那么有一个技巧。

删除重复的子序列O(n)

我们只需要关注长度为 2 的子序列,因为任何序列都可以表示为长度为 2 的重叠子序列。这一观察结果使我们能够保留这些对的数量,然后从右到左删除它们。

特别是,这只需要遍历列表固定的次数,因此是 O(n)

from collections import Counter

def remove_duplicates(lst):
    dropped_indices = set()
    counter = Counter(tuple(lst[i:i+2]) for i in range(len(lst) - 1))

    for i in range(len(lst) - 2, -1, -1):
        sub = tuple(lst[i:i+2])
        if counter[sub] > 1:
            dropped_indices |= {i, i + 1}
            counter[sub] -= 1

    return [x for i, x in enumerate(lst) if i not in dropped_indices]

这是一个基于提供的输入的示例。

a = [45874,
     35195, # This
     28965, # Is
     5867,  # A
     25847, # Subsequence
     94937,
     64894,
     55535,
     62899,
     391,
     35195, # Those
     28965, # Should
     5867,  # Be
     25847, # Removed
     8483]

b = remove_duplicates(a)
# Output:
#   [45874,
#    35195,
#    28965,
#    5867,
#    25847,
#    94937,
#    64894,
#    55535,
#    62899,
#    391,
#            <- Here the duplicate was removed
#    8483]

【讨论】:

    【解决方案2】:

    我使用以下方法进行了管理,可能效率不高:

    sequences=[] #all the sequences, as defined in question
    duplicated=[] #all the duplicated sequences
    for i in range(2, len(a)): #possible lengths of sequence
        n=0 # index of start of sequence
        for j in a:
            if n+i<=len(a): #if it's not too close to the end
                sequences.append(a[n:n+i]) #add the sequence
            n+=1
    tests=sequences[:] #duplicate so that I can remove for checking purposes
    for i in sequences:
        tests.remove(i)
        if i in tests: #if it's in there twice
            duplicated.append(i) #add it to the duplicates
    for i in duplicated:
        found=False #haven't found it yet
        n=0 #index we're at
        for j in a:
            if a[n:n+len(i)]==i and not found: #if it matches
                del a[n:n+len(i)] #remove it
                found=True #don't remove it again
            n+=1
    

    【讨论】:

    • 它删除了第一次而不是第二次出现,不知道这是否有问题......
    最近更新 更多