我正在尝试做

ls = [myfunc(a,b,i) for a in a_list for b in b_list]

但也将 i 传入 myfunc,它是一个从 0 开始并为每个新元素递增的索引。

例如:
a_list = 'abc'
b_list = 'def'

应该导致
ls = [myfunc('a','d',0),
      myfunc('a','e',1),
      myfunc('a','f',2),
      myfunc('b','d',3),
      myfunc('b','e',4),
      ...
      myfunc('c','f',8]

我知道我可以在正常情况下使用 enumerate(),即。
ls = [myfunc(a,i) for a,i in enumerate(a_list)]

但是当有两个 for 时,我无法弄清楚如何干净地做到这一点。我也找不到之前发布的这个问题。

最佳答案

您要在两个列表上创建 Cartesian product,因此请使用 itertools.product() 而不是双 for 循环。这为您提供了一个可迭代的,您可以轻松地将 enumerate() 添加到:

from itertools import product

ls = [myfunc(a, b, i) for i, (a, b) in enumerate(product(a_list, b_list))]

对于不能使用 product() 的情况,您可以将多个循环放入生成器表达式中,然后将 enumerate() 添加到其中。假设您需要过滤 a_list 的一些值:
gen = (a, b for a in a_list if some_filter(a) for b in b_list)
ls = [myfunc(a, b, i) for i, (a, b) in enumerate(gen)]

另一种选择是添加一个单独的计数器; itertools.count() 为您提供了一个计数器对象,该对象使用 next() 生成一个新值:
from itertools import count

counter = count()
ls = [myfunc(a, b, next(counter))
      for a in a_list if some_filter(a)
      for b in b_list]

毕竟,本质上 enumerate(iterable, start=0) 等同于 zip(itertools.count(start), iterable)

关于python - 如何用两个 'for' 枚举列表理解?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/51304270/

10-13 02:32