从Python列表中删除重复的整数序列

4
我有一个整数列表,需要去除其中的重复序列,但逻辑让我头痛。
我一直在尝试修改这个,以符合我的需求,但它只返回与重复序列长度相关的一个数字,并且只计算从起始整数开始的序列。
到目前为止,我已经做到了这一步:
def findRep(rmRepList):
    #Array to hold [starting position, length] of repeating sequences
    repList = []
    #For each industry listed
    for industry in rmRepList:
        #Maximum starting position
        maxStartPos = len(industry)-2
        #For each possible starting point of repetition
        for start in range(1,maxStartPos):
            #Limit on how long the repetition can be
            maxLen = math.ceil((len(industry)-start)/2)

            #For each possible length (2 because already canceled out repeating resources in genAllLoop)
            for i in range(2,maxLen):
                #If the next 'i' integers repeat
                if industry[start:i+start] is industry[i+start:2*i+start]:
                    repList = [start,i]
                    industry = rmRep(repList, industry)

                #If reached end of list
                if 2*i+start+1 == len(industry):
                    #End loop
                    break

def rmRep(rmProp, loop):
    #Sequence of resources to drop
    rmSeq = [loop[rmProp[0]:rmProp[0]+rmProp[1]]]
    #Debugging statement
    print(rmSeq)
    loop.remove(rmSeq)
    return(loop)name = username_entry.get()

rmRepList是一个列表的列表,其中每个列表都需要进行分析。

例如,如果给定一个列表

rmRepList = [[0,1,2,1,2,1,0],[0,1,2,1,2,1,2,3,4,5,3,4,5,6,0]]

我需要它返回[[0,1,2,1,0], [0,1,2,3,4,5,6,0]]

现在,代码甚至没有到达rmRep子程序。我有一种可怕的感觉,我做错了。我不喜欢代码中需要这么多循环,特别是实际要分析的列表长达数百位数。有更简单的方法吗?


编辑:如果有帮助,我可以保证列表中不会重复一个整数(例如[0,0,0,1,0]不会发生)。

此外,列表中的第一个和最后一个数字将始终相同。


1,2是重复的(不重叠)序列,因此被删除。 - jmbarbier
重复序列可以是任意长度还是只有一个固定长度? - wwii
重复的元素会紧挨着吗? [0,1,2,3,4,1,2] 可能吗?-> 你会移除哪一个? - wwii
提取的顺序很重要,还有提取较长的重复内容是否优先于较短的重复内容或反之亦然..? - wwii
如果很长时间内没有连续重复的序列(即彼此之后没有),那么它就能正常工作。我不知道除了在每一步之后检查所有可能长度的序列之外,你还能怎么做。因此,无论你是先检查长序列还是短序列,都不应该有影响。 - J. Doe
显示剩余2条评论
1个回答

3
答案的一部分:检测您的重复序列。
listA = [0,1,2,1,2,1,2,3,4,5,3,4,5,6,0]
listB = [0,1,2,1,2,1,0]

def get_repeated_seq(seq, start, length):
    ref = seq[start:start+length]
    #print("Ref", ref)
    for pos in range(start+length, len(seq)-length):
        compare = seq[pos:pos+length]
        #print("Pos", pos, compare)
        if compare == ref:
            print("Found", ref, "at", pos)
            return pos
    return False

def get_repeated_seqs(seq):
    for size in reversed(range(2, len(seq)/2)):
        for pos in range(0, len(seq)-size):
            print("Check rep starting at pos %s for size %s" % (pos, size))
            get_repeated_seq(seq, pos, size)

print(get_repeated_seqs(listA))

然后,您可以根据自己的删除策略(最大?最小?)将它们移除。

编辑:为了清楚起见,它可以运行(同时添加一些删除操作)。

listA = [0,1,2,1,2,1,2,3,4,5,2,1,3,4,5,2,1,6,0]
listB = [0,1,2,1,2,1,0]

def get_repeated_seq(seq, start, length):
    ref = seq[start:start+length]
    #print("Ref", ref)
    for pos in range(start+length, len(seq)-length):
        compare = seq[pos:pos+length]
        #print("Pos", pos, compare)
        if compare == ref:
            #print("Found", ref, "at", pos)
            return pos, length
    return False

def get_repeated_seqs(seq):
    reps = []
    for size in reversed(range(2, len(seq)/2)):
        for pos in range(0, len(seq)-size):
            #print("Check rep starting at pos %s for size %s" % (pos, size))
            rep = get_repeated_seq(seq, pos, size)
            if rep:
                reps.append(rep)
    return reps

def remove_repeated_seqs(seq, reps):
    # need to backup seq ?
    for rep in reps:
        overlaps = False
        for pos in range(rep[0], rep[0]+rep[1]):
            if seq[pos] == "*":
                overlaps = True
        if not overlaps:
            for pos in range(rep[0], rep[0]+rep[1]):
                seq[pos] = "*"
    out = []
    for item in seq:
        if item != "*":
            out.append(item)
    return out


reps = get_repeated_seqs(listB)
rem = remove_repeated_seqs(listB, reps)
#print(rem)
print(rem==[0,1,2,1,0])

reps = get_repeated_seqs(listA)
rem = remove_repeated_seqs(listA, reps)
#print(rem)
print(rem==[0,1,2,3,4,5,6,0])

输出结果为True和True :)

编辑2:在for range循环中不需要使用-1来到达列表的末尾。


哇,太棒了!天啊,StackOverflow上的人都是巫师,我一早上都在看这个问题,但还是没有进展。现在我要删除所有重复序列,这应该不难。干杯! - J. Doe
对于边缘情况:[0,1,2,1,2,1,2,3,4,5,2,1,3,4,5,2,1,6,0] 是一个麻烦的样本... (2,1) 是(3,4,5,2,1) 这个大序列的一部分,并且也是从 (2,1) 重复出现的... 因此,删除策略必须比仅仅“删除重复项”更好地定义。 - jmbarbier
嗯,你提出了一个很好的观点。最初,我想删除的序列是连续的。在你提到的情况下,这意味着它变成了 [0,1,2,3,4,5,2,1,6,0]。话虽如此,我刚刚发现,根据我已经设置的内容,我只需要检测其中有重复的列表(因为我第一次创建列表时的偶然),然后删除它们。 - J. Doe
我不认为那是问题所在,因为那时我没有调用ListB。请注意,我尝试的是[0, 1, 2, 1, 2, 0],而不是[0,1,2,1,2,1,0](倒数第二个数字)。无论如何,我已经成功地使用了另一种方法。这并不能真正帮助任何想要解决类似问题的人,因为它特定于我生成列表的方式。如果我以后有时间,我会尝试将其分离并发布我的解决方案。无论如何,你的代码绝对是一个很好的起点,所以感谢你 :) - J. Doe
你说得对!!.. for pos in range(start+length, len(seq)-length): 中的-1 :( 无论如何,你的问题很有趣,我的学生们很快就会尝试它。 - jmbarbier
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接