在 python 列表中找到第二个重复项和句点

find second duplicate and period in a python list

我有一个 python 列表为这个 [2, 5, 26, 37, 45, 12, 23, 37, 45, 12, 23, 37, 45, 12, 23, 37 ].真正的名单真的很长。在这种情况下,列表会在 37 之后的某个点后自行重复。我可以毫无问题地找到它重复的数字,但我需要在第二个位置截断列表。在这种情况下,结果将是 [2, 5, 26, 37, 45, 12, 23, 37]。为了找到数字(在本例中为 37),我使用了在 Whosebug 上找到的函数 firstDuplicate()。有人可以帮助我吗?

def firstDuplicate(a):
aset = set()
for i in a:
    if i in aset:
        return i
    else:
        aset.add(i)
        pass
    pass
pass
LIST = LIST[1:firstDuplicate(LIST)]

您可以使用与 firstDuplicate() 相同的基本思想,并创建一个生成值的生成器,直到找到重复项。然后传给list(),循环等

l = [2, 5, 26, 37, 45, 12, 23, 37, 45, 12, 23, 37, 45, 12, 23, 37]

def partitionAtDupe(l):
    seen = set()
    for n in l:
        yield n
        if n in seen:    
            break
        seen.add(n)


list(partitionAtDupe(l))
# [2, 5, 26, 37, 45, 12, 23, 37]

不清楚如果没有骗子会发生什么。在这种情况下,上面的代码将生成整个列表。

查找周期大小和重复数字长度的函数应从数字序列的末尾开始。这将更容易确保循环到列表的末尾,并避免对列表开头的非周期性重复的任何担忧。

例如:

def getPeriod(seq):
    lastPos = { n:p for p,n in enumerate(seq) }                 
    prevPos = { n:p for p,n in enumerate(seq) if p<lastPos[n] }
    period  = 1
    for n in reversed(seq):
        if n not in prevPos: break
        delta = lastPos[n] - prevPos[n]
        if delta%period == 0 or period%delta == 0:
            period = max(delta,period)
        else: break
    nonPeriodic  = (i for i,(n,p) in enumerate(zip(seq[::-1],seq[-period-1::-1])) if n != p)
    periodLength = next(nonPeriodic,0)
    return period, periodLength

输出:

seq     = [2, 5, 26, 37, 45, 12, 23, 37, 45, 12, 23, 37, 45, 12, 23, 37]

period, periodLength = getPeriod(seq)

print(period,periodLength) # 4 9
print(seq[:-periodLength]) # [2, 5, 26, 37, 45, 12, 23]