Python 使用itertools从某一点连续排列
我有一大组排列,我想跑来跑去Python 使用itertools从某一点连续排列,python,permutation,Python,Permutation,我有一大组排列,我想跑来跑去 from itertools import permutations perms = permutations([0,1,2,3,4,5,6,7,8,9,10,11,12,13,15,16], 6) 我正在使用一个简单的下一个调用来降低内存使用率 combination = perm.next() processing = True while processing: try: # using combination in code t
from itertools import permutations
perms = permutations([0,1,2,3,4,5,6,7,8,9,10,11,12,13,15,16], 6)
我正在使用一个简单的下一个调用来降低内存使用率
combination = perm.next()
processing = True
while processing:
try:
# using combination in code then end by calling next
# do_work(combination)
combination = perm.next()
except:
print(combination) # (0,1,2,3,4,23)
processing = False
这一切都很好。但我注意到,如果我停止它,我必须重新开始。
有没有办法从我跑的最后一点开始继续
例如:
(0,1,2,3,4,23)
下一步工作在哪里:
(0,1,2,3,4,24)
?
更新:许多伟大的解决方案!谢谢大家您可以定义一个类来管理排列,其行为类似于列表:
from math import factorial
from collections.abc import Sequence
class Permutations(Sequence):
def __init__(self,data,samples=None):
self._data = data
self._samples = samples
self._size = 0
self._lenData = 0
def __len__(self):
if self._lenData != len(self._data):
self._lenData = len(self._data)
samples = min(self._lenData,self._samples or self._lenData)
self.size = factorial(self._lenData)//factorial(self._lenData-samples)
return self.size
def __getitem__(self,index):
if isinstance(index,slice):
return map(self.__getitem__,range(len(self))[index])
scale = len(self)
remaining = list(self._data)
result = []
for p in range(min(self._lenData,self._samples or self._lenData)):
scale //= (len(self._data)-p)
i,index = divmod(index,max(1,scale))
result.append(remaining.pop(i))
return tuple(result)
该类不使用额外的存储,只使用两个整数来管理大小更改。它甚至支持对引用列表进行即时更改
示例用法:
L = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,15,16]
P = Permutations(L,6)
len(P) # 5765760
P[6] # (0, 1, 2, 3, 4, 11)
for perm in P[6:16]: print(perm)
(0, 1, 2, 3, 4, 11)
(0, 1, 2, 3, 4, 12)
(0, 1, 2, 3, 4, 13)
(0, 1, 2, 3, 4, 15)
(0, 1, 2, 3, 4, 16)
(0, 1, 2, 3, 5, 4)
(0, 1, 2, 3, 5, 6)
(0, 1, 2, 3, 5, 7)
(0, 1, 2, 3, 5, 8)
(0, 1, 2, 3, 5, 9)
for perm in P[-3:]: print(perm)
(16, 15, 13, 12, 11, 8)
(16, 15, 13, 12, 11, 9)
(16, 15, 13, 12, 11, 10)
若要从您停止的位置重新开始,您可以存储索引或排列。由于类的行为类似于列表,因此可以使用对分模块从已知排列中获取下一个索引:
from bisect import bisect_right
lastPermute = P[123] # (0, 1, 2, 3, 16, 6)
i = bisect_right(P,lastPermute)
print(i) # 124
您甚至可以使用它获得随机排列,而无需在列表中生成所有排列:
random.choice(P)
(9, 7, 10, 5, 2, 4)
random.sample(P,3)
[(15, 0, 13, 8, 10, 9), (9, 13, 3, 4, 8, 10), (1, 12, 0, 3, 6, 9)]
您可以将其pickle到文件中并重新加载以继续下一次运行 开始使用它:
>>> from itertools import permutations, islice
>>> perms = permutations([0,1,2,3,4,5,6,7,8,9,10,11,12,13,15,16], 6)
>>> *islice(perms, 3),
((0, 1, 2, 3, 4, 5), (0, 1, 2, 3, 4, 6), (0, 1, 2, 3, 4, 7))
保存状态以备以后使用(实际上会放入文件):
您可以跟踪已完成的运行次数,保存该数字,然后下次使用
itertools.islice(seq,start)
“我必须重新开始”-不正确。只需确保将perm
保留在范围内,然后你就不必重新开始了。你有没有打算给我们展示一个所谓必须重新开始的演示?凯利,我能建议的是你重新阅读这个问题,因为除了你自己,其他人似乎都知道发生了什么。你似乎认为我的非最小片段存在排列。你跟next有麻烦吗?使用uuu next uuuuuuuu()无论如何,我很快就可以根据@BallpointBen的评论来解决这个问题。很好的类,但我需要数组的长度为6,最大值为16。我想len
不会是一件很常见的事情,所以我建议将大小计算移到\uuu len
中。另外,如果您定义了\uuuuu len\uuuuu
和\uuuuu getitem\uuuuuuu
,则不需要定义\uuuuuu iter\uuuuuuu
。调整类以支持大量示例。@AlainT。仅供参考,您最近的更改破坏了您的代码。可能是中间保存,现已修复。非常好的解决方案+1.对我来说。。我也要试试这个
>>> import pickle
>>> pickled = pickle.dumps(perms)
>>> type(pickled), len(pickled)
(<class 'bytes'>, 135)
>>> restored = pickle.loads(pickled)
>>> *islice(restored, 3),
((0, 1, 2, 3, 4, 8), (0, 1, 2, 3, 4, 9), (0, 1, 2, 3, 4, 10))