如何在列表的笛卡尔积中进行迭代

15

我想使用for循环迭代3个(或任意数量)列表,每个列表中有任意数量的元素,例如:

from itertools import izip
for x in izip(["AAA", "BBB", "CCC"], ["M", "Q", "S", "K", "B"], ["00:00", "01:00", "02:00", "03:00"]):
    print x

但是它给了我:

('AAA', 'M', '00:00')
('BBB', 'Q', '01:00')
('CCC', 'S', '02:00')

我想要:

('AAA', 'M', '00:00')
('AAA', 'M', '01:00')
('AAA', 'M', '02:00')
.
.

('CCC', 'B', '03:00')

实际上我想要的是:

for word, letter, hours in [cartesian product of 3 lists above]
    if myfunction(word,letter,hours):
       var_word_letter_hours += 1
3个回答

23
你想要使用列表的product
from itertools import product

for word, letter, hours in product(["AAA", "BBB", "CCC"], ["M", "Q", "S", "K", "B"], ["00:00", "01:00", "02:00", "03:00"]):

演示:

>>> from itertools import product
>>> for word, letter, hours in product(["AAA", "BBB", "CCC"], ["M", "Q", "S", "K", "B"], ["00:00", "01:00", "02:00", "03:00"]):
...     print word, letter, hours
... 
AAA M 00:00
AAA M 01:00
AAA M 02:00
AAA M 03:00
...
CCC B 00:00
CCC B 01:00
CCC B 02:00
CCC B 03:00

7
使用 itertools.product
import itertools

for x in itertools.product(["AAA", "BBB", "CCC"],
                           ["M", "Q", "S", "K", "B"],
                           ["00:00", "01:00", "02:00", "03:00"]):
    print x

输出:

('AAA', 'M', '00:00')
('AAA', 'M', '01:00')
...
('CCC', 'B', '02:00')
('CCC', 'B', '03:00')

1

仅供参考,另一种解决方案是嵌套的for循环:

for a in ["AAA", "BBB", "CCC"]:
    for b in ["M", "Q", "S", "K", "B"]:
       for c in ["00:00", "01:00", "02:00", "03:00"]:
           x = (a, b, c)
           # Use x ...

在我看来,这比查找/记住 itertools.product 函数要清晰得多。唯一使用它的好理由是如果您处于更抽象的情况下;例如,您需要将迭代器传递给函数而不是立即迭代它,或者如果您有一个任意列表的列表,您想要获取其笛卡尔积(在这种情况下,您可以使用product(*lists))。

如果您需要在不同的循环级别上进行额外的处理,那么这个解决方案更有意义。然而,原帖作者只想迭代三元组,在这种方法中必须手动构建。嵌套的 for 循环会添加与列表数量相同的缩进,这可能会对可读性造成真正的问题。 - user4815162342
1
如果嵌套循环的数量在编译时(或者你想在Python中称之为编译时)不知道,那么这也是不好的。 - FinanceGuyThatCantCode
@FinanceGuyThatCantCode 我已经在我的回答中明确提到了这一点,我说如果你有一个任意的列表列表想要取笛卡尔积,那么这样做是没有好处的。 - Arthur Tacca

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接