我正在使用itertools
运行数值模拟,迭代我输入参数的所有可能组合。在下面的示例中,我有两个参数和六种可能的组合:
import itertools
x = [0, 1]
y = [100, 200, 300]
myprod = itertools.product(x, y)
for p in myprod:
print p[0], p[1]
# run myfunction using p[0] as the value of x and p[1] as the value of y
如何获得myprod
的大小(示例中为6)?我需要在for
循环开始之前打印它。
我理解myprod
不是列表。我可以计算len(list(myprod))
,但这会消耗迭代器,因此for
循环不再有效。
我试过了:
myprod2=copy.deepcopy(myprod)
mylength = len(list(myprod2))
但这也行不通。我能做到:
myprod2=itertools.product(x,y)
mylength = len(list(myprod2))
但它不是优雅和pythonic!
答案 0 :(得分:10)
为任意数量的源迭代项实施Kevin's answer,合并reduce
和mul
:
>>> import functools, itertools, operator
>>> iters = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> functools.reduce(operator.mul, map(len, iters), 1)
27
>>> len(list(itertools.product(*iters)))
27
请注意,如果您的源迭代器本身是迭代器而不是序列,这将无效,原因与初始尝试获取itertools.product
的长度失败的原因相同。 Python和itertools
通常可以使用任何长度的迭代器(包括无限!)以高效内存的方式工作,因此预先找出长度并不是它设计用来处理的情况。< / p>
答案 1 :(得分:2)
怎么样:
mylength = len(x) * len(y)
答案 2 :(得分:1)
虽然这不能直接回答问题,但很多时候我们希望找到生成器的长度以估计进度/运行时间。
为此,请考虑在生成器函数周围使用tqdm
(版本> = 4.42.0)包装,不要忘记迭代器的长度(tqdm
是一个progressbar库)。例如,
from tqdm.contrib.itertools import product
from time import sleep
for i, j in product(range(3), range(4)):
sleep(1)
将显示进度条。产品的长度显示为total
对象的tqdm
(例如,显示的6
中的3/6 [00:03<00:03]
)。
答案 3 :(得分:0)
我使用的替代解决方案:
import itertools
param = (('a', 'b'), (1, 2)) # a list of lists
# Calculate all combinations
combinations = itertools.product(*param)
# Calculate number of combinations
total_combinations = 1
for i in param:
total_combinations = total_combinations * len(i)