合并itertools.product的结果?
我正在尝试用 itertools.product
创建一个从 0-9999
的数字列表。我可以通过以下方式创建一个从 0000-9999
的列表:
numbers = ['0','1','2','3','4','5','6','7','8','9']
itertools.product(numbers,numbers,numbers,numbers)
我希望得到像 0001
这样的条目,但我也想要 001
、01
和 1
这些形式。
那么,最有效的方法是什么呢?我应该调用 itertools.product(numbers,numbers,numbers)
和 itertools.product(numbers,numbers)
,然后把这些结果和原来的结合起来,还是有更简单的方法呢?
如果我需要再调用两个其他的函数并进行合并,有人能告诉我该怎么做吗?我尝试使用 .append()
,但出现了这个错误:
'itertools.product' object has no attribute 'append'
谢谢大家的帮助。
3 个回答
对现有答案的性能提升:
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 这个参考解释器上,性能会显著提升(虽然在这个例子中提升不大,但对于更大的数据集来说效果会非常明显),原因如下:
- 大部分工作都转移到了 C 语言层面,这样就避免了字节码解释器的循环开销。
product
有一个优化,可以重用结果中的tuple
(这意味着在请求下一个结果时,不需要设置大部分值),前提是没有引用存在。这个优化在列表推导和生成表达式中不可用,因为它们的循环结构会让结果的tuple
保持引用,直到判断是否可以重用这个tuple
。而map(''.join
则避免了这个问题(它只在调用映射函数时保持对tuple
的引用,之后就丢弃了它)。
即使在这个例子中,速度提升也是相当显著的,具体的提升通过 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 微秒在整体上看是微不足道的。但如果需要处理的 range
更大,或者要计算的 numbers
集合更大,这个提升就显得更重要了;对于 numbers = '0123456789'
和 range(1, 8)
,运行时间从 2.54 秒减少到 1.67 秒;从长远来看,节省的时间大约是三分之一,当总时间以秒为单位计算时,减少三分之一的时间是非常有意义的。
在编程中,有时候我们会遇到一些问题,比如代码运行不正常。这种情况可能是因为代码中有错误,或者是我们没有正确使用某些功能。为了找到问题所在,我们可以使用一些工具和方法来帮助我们调试,也就是找出错误并修复它们。
调试的过程就像是侦探在寻找线索。我们可以逐步检查代码的每一部分,看看哪里出了问题。通常,我们会在代码中添加一些打印语句,这样可以在运行时看到变量的值和程序的执行情况。这就像是在代码中放置了小标记,帮助我们追踪程序的运行路径。
此外,很多编程环境提供了调试工具,可以让我们逐行执行代码,观察每一步的变化。这些工具就像是放大镜,让我们能更清楚地看到代码的细节。
总之,调试是编程中非常重要的一部分,它帮助我们理解代码的运行情况,并找到并修复问题。通过不断练习,我们会变得越来越熟练。
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)))
你可以使用嵌套的列表推导式或者生成器表达式(这里为了显示方便,缩减了一些内容):
>>> 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']