这是一个基于pypy库代码的解决方案(感谢agf在评论中的建议)。
状态可以通过
.state属性获得,也可以通过
.goto(state)位置
state序列的索引(从0开始)进行重置。最后有一个演示(恐怕您需要向下滚动)。
这比丢弃值要快得多。
> cat prod.pyclass product(object): def __init__(self, *args, **kw): if len(kw) > 1: raise TypeError("product() takes at most 1 argument (%d given)" % len(kw)) self.repeat = kw.get('repeat', 1) self.gears = [x for x in args] * self.repeat self.num_gears = len(self.gears) self.reset() def reset(self): # initialization of indicies to loop over self.indicies = [(0, len(self.gears[x])) for x in range(0, self.num_gears)] self.cont = True self.state = 0 def goto(self, n): self.reset() self.state = n x = self.num_gears while n > 0 and x > 0: x -= 1 n, m = divmod(n, len(self.gears[x])) self.indicies[x] = (m, self.indicies[x][1]) if n > 0: self.reset() raise ValueError("state exceeded") def roll_gears(self): # Starting from the end of the gear indicies work to the front # incrementing the gear until the limit is reached. When the limit # is reached carry operation to the next gear self.state += 1 should_carry = True for n in range(0, self.num_gears): nth_gear = self.num_gears - n - 1 if should_carry: count, lim = self.indicies[nth_gear] count += 1 if count == lim and nth_gear == 0: self.cont = False if count == lim: should_carry = True count = 0 else: should_carry = False self.indicies[nth_gear] = (count, lim) else: break def __iter__(self): return self def next(self): if not self.cont: raise StopIteration l = [] for x in range(0, self.num_gears): index, limit = self.indicies[x] l.append(self.gears[x][index]) self.roll_gears() return tuple(l)p = product('abc', '12')print list(p)p.reset()print list(p)p.goto(2)print list(p)p.goto(4)print list(p)> python prod.py [('a', '1'), ('a', '2'), ('b', '1'), ('b', '2'), ('c', '1'), ('c', '2')][('a', '1'), ('a', '2'), ('b', '1'), ('b', '2'), ('c', '1'), ('c', '2')][('b', '1'), ('b', '2'), ('c', '1'), ('c', '2')][('c', '1'), ('c', '2')]
您应该对其进行更多测试-我可能犯了一个愚蠢的错误-但是这个想法很简单,因此您应该可以解决它:o)您可以自由使用我的更改;不知道原始的pypy许可证是什么。
也不
state是真正的完整状态-它不包括原始参数-只是序列的索引。也许最好把它称为索引,但是代码中已经有索引了。
更新
这是一个简单的版本,具有相同的想法,但是可以通过转换数字序列来工作。因此,您只需将
imap其
count(n)偏移量即可
n。
> cat prod2.pyfrom itertools import count, imapdef make_product(*values): def fold((n, l), v): (n, m) = divmod(n, len(v)) return (n, l + [v[m]]) def product(n): (n, l) = reduce(fold, values, (n, [])) if n > 0: raise StopIteration return tuple(l) return productprint list(imap(make_product(['a','b','c'], [1,2,3]), count()))print list(imap(make_product(['a','b','c'], [1,2,3]), count(3)))def product_from(n, *values): return imap(make_product(*values), count(n))print list(product_from(4, ['a','b','c'], [1,2,3]))> python prod2.py [('a', 1), ('b', 1), ('c', 1), ('a', 2), ('b', 2), ('c', 2), ('a', 3), ('b', 3), ('c', 3)][('a', 2), ('b', 2), ('c', 2), ('a', 3), ('b', 3), ('c', 3)][('b', 2), ('c', 2), ('a', 3), ('b', 3), ('c', 3)]
(这里的缺点是,如果您要停止并重新启动,则需要跟踪自己已使用了多少个)
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)