【问题标题】:How to get the length of an itertools.product?如何获得 itertools.product 的长度?
【发布时间】:2015-11-11 12:22:57
【问题描述】:

我正在使用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 的大小(示例中为六)?我需要在for 循环开始之前打印它。

我知道myprod 不是一个列表。我可以计算len(list(myprod)),但这会消耗迭代器,因此for 循环不再起作用。

我试过了:

myprod2=copy.deepcopy(myprod)
mylength = len(list(myprod2))

但这也不起作用。我可以这样做:

myprod2=itertools.product(x,y)
mylength = len(list(myprod2))

但它并不优雅和pythonic!

【问题讨论】:

  • 获取迭代器的长度没有意义,而且有点破坏了使用迭代器的意义!不过,您可以解决...“这用完了(正确的术语是什么?)” - “消耗”,一般来说.
  • 嗯,在我的具体情况下确实很有意义,因为(由于这里解释的原因太长)我需要在 for 循环开始之前获取组合总数
  • 但是一般来说,由于迭代器不一定是有限的,如果不消耗它们就无法找出长度。
  • 当然可以,但是对于我的迭代器总是有限的特定情况,你会推荐什么?你会推荐使用 itertools 以外的东西吗?

标签: python itertools


【解决方案1】:

为任意数量的源迭代实现Kevin's answer,结合reducemul

>>> 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 特别是可以使用任何长度(包括无限!)的迭代器以节省内存的方式工作,因此预先找出长度并不是它旨在处理的情况。

【讨论】:

    【解决方案2】:

    虽然这不能直接回答问题,但我们经常希望找到生成器的长度来估计进度/运行时间。

    为此,请考虑使用 tqdm(版本 >= 4.42.0)的包装器围绕不会忘记迭代器长度的生成器函数(tqdm 是一个进度条库)。例如,

    from tqdm.contrib.itertools import product
    from time import sleep
    for i, j in product(range(3), range(4)):
        sleep(1)
    

    将显示一个进度条。产品的长度显示为tqdm 对象的total(例如,3/6 [00:03<00:03] 中的6 所示)。

    【讨论】:

      【解决方案3】:

      怎么样:

      mylength = len(x) * len(y)
      

      【讨论】:

      • 在我的具体情况下不太方便,因为我没有两个输入但更多
      • @Pythonistaan​​onymous 但它仍然只是源迭代器长度的乘积(Python 3.x 中的functools.reduce(operator.mul, map(len, iters), 1))。
      • 我对此投了反对票,因为它没有回答问题。例如,我有一个传递 itertools.product 的程序。这个聪明的把戏是行不通的。
      【解决方案4】:

      我使用的替代解决方案:

      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)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2010-12-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多