0

我有一个 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),我使用了在 stackoverflow 上找到的函数 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)]
4

2 回答 2

0

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

例如:

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]
于 2020-05-15T17:36:40.473 回答
0

您可以使用相同的基本思想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]

目前尚不清楚如果没有受骗者会发生什么。在这种情况下,上面的代码将产生整个列表。

于 2020-05-15T16:24:42.330 回答