合并itertools.product的结果?

时间:2014-08-30 03:36:07

标签: python itertools

我正在尝试使用0-9999itertools.product创建一个数字列表。我可以通过执行以下操作从0000-9999创建一个列表:

numbers = ['0','1','2','3','4','5','6','7','8','9']
itertools.product(numbers,numbers,numbers,numbers)

虽然我想要0001之类的条目,但我还希望得到001011

包含这些内容的最有效方法是什么?我应该拨打itertools.product(numbers,numbers,numbers)itertools.product(numbers,numbers),然后以某种方式将这些与原始电话结合起来,还是有更清洁的方式?

如果我应该另外打两个电话并结合,有人可以指出我将如何做到这一点?我尝试使用.append(),但它会抛出此错误:

'itertools.product' object has no attribute 'append'

感谢您的帮助。

3 个答案:

答案 0 :(得分:3)

您可以使用嵌套的listcomp或genexp(此处缩小尺寸以用于显示目的):

>>> numbers = ['0','1','2']
>>> [''.join(p) for n in range(1,4) for p in product(numbers, repeat=n)]
['0', '1', '2', '00', '01', '02', '10', '11', '12', '20', '21', '22', '000', '001', '002', '010', '011', '012', '020', '021', '022', '100', '101', '102', '110', '111', '112', '120', '121', '122', '200', '201', '202', '210', '211', '212', '220', '221', '222']

答案 1 :(得分:1)

numbers = ['0','1','2','3','4','5','6','7','8','9']
list(''.join(subl) for subl in itertools.chain.from_iterable(itertools.product(numbers, repeat=i) for i in range(1,5)))

答案 2 :(得分:0)

现有答案的性能改进:

from itertools import chain, product

list(map(''.join, chain.from_iterable(product(numbers, repeat=i) for i in range(1, 5))))
# Or on Python 3.5+ with additional unpacking generalizations:
[*map(''.join, chain.from_iterable(product(numbers, repeat=i) for i in range(1, 5)))]

如果只是迭代结果,则省略list() / [*...]换行。

在CPython参考解释器上,性能显着提高(在这种情况下并没有很大提高,但对于较大的产品却显着提高了)(实现细节在这里):

  1. 它将大部分工作推到C层,避免了字节码解释器循环开销
  2. 如果在请求下一个结果时不存在引用,则
  3. product具有an optimization that reuses the result tuple(包括不需要设置其中的大多数值)。此优化不适用于listcomps和genexprs(循环结构将对生成的tuple的引用保持有效的时间足够长,以至于在确定是否可以将tuple用于下一个结果时使用该引用),但map(''.join避免了这一点(它仅保存对tuple的引用足够长的时间以调用mapper函数,在产生mapper结果之前将其丢弃)。

即使在这种情况下,也可以通过ipython微型基准(在这种情况下,在Linux x64 3.6安装上)进行演示,从而可以显着提高百分比。

>>> %timeit -r5 [''.join(p) for n in range(1, 5) for p in product(nums, repeat=n)]
24.9 μs ± 95.2 ns per loop (mean ± std. dev. of 5 runs, 10000 loops each)
>>> %timeit -r5 list(map(''.join, chain.from_iterable(product(numbers, repeat=i) for i in range(1, 5))))
18.2 μs ± 41.2 ns per loop (mean ± std. dev. of 5 runs, 100000 loops each)

如前所述,这里的收益仅以百分比表示(运行时间减少了约27%);在宏伟的方案中,6.7μs相当微不足道。但是,如果要覆盖的range变大和/或numbersproduct的集合变大,那就更重要了;对于numbers = '0123456789'range(1, 8),减少时间从2.54 s减少到1.67 s;渐近地,节省似乎是节省了大约三分之一,而以秒为单位衡量总成本时,将成本减少三分之一是有意义的。

相关问题