我正在循环使用多个迭代器,每个迭代器都可以取 0 到 193 之间的值,并且每个迭代器还必须大于前一个迭代器 (i1 < i2 < i3 … < in)。
对于这个例子,我有 5 个迭代器;要迭代的状态总数非常大 (2,174,032,288)。因此,我正在分批处理这些状态并保存每批的开始和最终“状态”,这样我就可以从它停止的地方继续。
我的以下代码有效。我的问题是什么是概括这些嵌套 if 语句的最佳方法,以便它适用于任意数量的有序迭代器,而不仅仅是 5 个。此外,是否有更好的方法来实现这一点?
rnIndex = [0, 1, 2, 3, 4] # the starting state of indices to iterate from batchSize = 1000000 # iterate through 1 million index states per batch batchNumber = 0 # the batch number to start from - 1 batchNumberMax = 10 # run up to and including this batch number rnLimit = 194 # iterate up to (but not including) for each index rnComplete = False while not rnComplete and batchNumber < batchNumberMax: batchNumber += 1 print('\nStart index (included): ' + str(rnIndex)) rnBatch = [] for i in range(batchSize): if i == batchSize - 1: print('Final index (included): ' + str(rnIndex)) rnBatch.append(rnIndex) # add each rnIndex to rnBatch rnIndex[-1] += 1 if rnIndex[-1] == rnLimit: rnIndex[-2] += 1 rnIndex[-1] = rnIndex[-2] + 1 if rnIndex[-2] == rnLimit - 1: rnIndex[-3] += 1 rnIndex[-2] = rnIndex[-3] + 1 rnIndex[-1] = rnIndex[-2] + 1 if rnIndex[-3] == rnLimit - 2: rnIndex[-4] += 1 rnIndex[-3] = rnIndex[-4] + 1 rnIndex[-2] = rnIndex[-3] + 1 rnIndex[-1] = rnIndex[-2] + 1 if rnIndex[-4] == rnLimit - 3: rnIndex[-5] += 1 rnIndex[-4] = rnIndex[-5] + 1 rnIndex[-3] = rnIndex[-4] + 1 rnIndex[-2] = rnIndex[-3] + 1 rnIndex[-1] = rnIndex[-2] + 1 if rnIndex[-5] == rnLimit - 4: rnComplete = True break print('len(rnBatch) = '+str(len(rnBatch))) # check the length of rnBatch print(rnIndex) # the rnIndex state to resume from
出去:
Start index (included): [0, 1, 2, 3, 4] Final index (included): [0, 1, 94, 99, 133] len(rnBatch) = 1000000 ... Start index (included): [0, 8, 24, 122, 173] Final index (included): [0, 9, 23, 54, 90] len(rnBatch) = 1000000 Start index (included): [0, 9, 23, 54, 91] Final index (included): [0, 10, 22, 182, 188] len(rnBatch) = 1000000 [0, 10, 22, 182, 189] Process finished with exit code 0
您可以编写一个函数,根据前一个索引生成下一个索引序列,并使用它从任何起点推进组合:
def nextSeq(maxVal,values): for i,v in enumerate(reversed(values),1): if v <= maxVal-i: return values[:-i]+[values[-i]+k+1 for k in range(i)]
输出:
seq = [0,1,2,3,4] for _ in range(10): print(seq) seq = nextSeq(193,seq) [0, 1, 2, 3, 4] [0, 1, 2, 3, 5] [0, 1, 2, 3, 6] [0, 1, 2, 3, 7] [0, 1, 2, 3, 8] [0, 1, 2, 3, 9] [0, 1, 2, 3, 10] [0, 1, 2, 3, 11] [0, 1, 2, 3, 12] [0, 1, 2, 3, 13]
该函数还可用于创建可在 for 循环(无嵌套)中使用的生成器:
def genSeq(maxVal,start): seq = list(start) while seq: yield seq seq = nextSeq(maxVal,seq)
start = [188,189,190,191,192] for seq in genSeq(193,start): print(seq) [188, 189, 190, 191, 192] [188, 189, 190, 191, 193] [188, 189, 190, 192, 193] [188, 189, 191, 192, 193] [188, 190, 191, 192, 193] [189, 190, 191, 192, 193]
如果你想直接跳转到特定的序列(第N个序列),递归函数可以将索引转换为顺序相同的序列:
from math import factorial as fact def seqAtIndex(index,maxVal,size): if size == 1: return [index] value = base = chunk = 0 while base+chunk <= index: base += chunk value += 1 chunk = fact(maxVal+1-value)//fact(size-1)//fact(maxVal+2-value-size) return [value-1] \ + [value+s for s in seqAtIndex(index-base,maxVal-value,size-1)]
for i in range(10): print(i,seqAtIndex(i,193,5)) 0 [0, 1, 2, 3, 4] 1 [0, 1, 2, 3, 5] 2 [0, 1, 2, 3, 6] 3 [0, 1, 2, 3, 7] 4 [0, 1, 2, 3, 8] 5 [0, 1, 2, 3, 9] 6 [0, 1, 2, 3, 10] 7 [0, 1, 2, 3, 11] 8 [0, 1, 2, 3, 12] 9 [0, 1, 2, 3, 13] for i in range(2174032280,2174032288): print(i,seqAtIndex(i,193,5)) 2174032280 [187, 189, 191, 192, 193] 2174032281 [187, 190, 191, 192, 193] 2174032282 [188, 189, 190, 191, 192] 2174032283 [188, 189, 190, 191, 193] 2174032284 [188, 189, 190, 192, 193] 2174032285 [188, 189, 191, 192, 193] 2174032286 [188, 190, 191, 192, 193] 2174032287 [189, 190, 191, 192, 193]
请注意,它比orseqAtIndex慢得多,所以您应该只使用它来查找起始序列,然后使用其他函数按顺序前进nextSeq``genSeq
seqAtIndex
nextSeq``genSeq