简体   繁体   English

如何用两个'for'列举列表理解?

[英]How do I enumerate a list comprehension with two 'for's?

I am trying to do 我想做

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

but also pass in i into myfunc, which is an index starting at 0 and incrementing for each new element. 但也将i传入myfunc,这是一个从0开始的索引,并为每个新元素递增。

For example: 例如:

a_list = 'abc'
b_list = 'def'

should result in 应该导致

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]

I know that I can use enumerate() for just the normal case, ie. 我知道我可以使用enumerate()来表示正常情况,即。

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

But I can't figure out how to do it cleanly when there are two for s. 但我无法弄清楚如何做到这一点干净的时候有两个for秒。 I couldn't find this question posted previously either. 我以前找不到这个问题。

You are creating a Cartesian product over two lists, so use itertools.product() instead of a double for loop. 您正在两个列表上创建笛卡尔积 ,因此请使用itertools.product()而不是double for循环。 This gives you a single iterable you can easily add enumerate() to: 这为您提供了一个可迭代的,您可以轻松地将enumerate()添加到:

from itertools import product

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

For cases where you can't use product() , you'd put the multiple loops in a generator expression, then add enumerate() to that. 对于无法使用product()情况,您可以将多个循环放在生成器表达式中,然后将enumerate()添加到该表达式中。 Say you needed to filter some values of a_list : 假设您需要过滤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)]

Another option is to add a separate counter; 另一种选择是增加一个单独的柜台; itertools.count() gives you a counter object that produces a new value with next() : 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]

After all, in essence enumerate(iterable, start=0) is the equivalent of zip(itertools.count(start), iterable) . 毕竟,实质上enumerate(iterable, start=0)相当于zip(itertools.count(start), iterable)

You can use enumerate on the sequence of pairs. 您可以在对序列上使用枚举。

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

For a simple nested loop, use itertools.product() as @Martijn suggested. 对于一个简单的嵌套循环,请使用itertools.product()作为@Martijn建议。

If the expression is more complex you can use itertools.count : 如果表达式更复杂,可以使用itertools.count

i_gen = itertools.count()
ls = [myfunc(a, b, next(i_gen)) for a in a_list for b in b_list]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM