在Python中迭代多个列表中的所有值的组合

76

给定可能长度不同的多个列表,我希望迭代每个值的所有组合,每个列表中选取一个元素。例如:

first = [1, 5, 8]
second = [0.5, 4]

那么我希望输出的结果为:

combined = [(1, 0.5), (1, 4), (5, 0.5), (5, 4), (8, 0.5), (8, 4)]

我想迭代遍历这个合并的列表,我该如何做到?

2个回答

133

itertools.product 应该可以解决问题。

>>> import itertools
>>> list(itertools.product([1, 5, 8], [0.5, 4]))
[(1, 0.5), (1, 4), (5, 0.5), (5, 4), (8, 0.5), (8, 4)]
请注意,itertools.product 返回一个迭代器,因此如果你只想迭代一次,则不需要将其转换为列表。
例如:
for x in itertools.product([1, 5, 8], [0.5, 4]):
    # do stuff

如果 second = [0.5, 4, 1],并且我们认为输出 (1, 4) 和输出 (4, 1) 是相同的,那么怎么办? - Nate Anderson
1
@TheRedPea(假设您在第一个列表中有一个4,并且您希望结果中仅有唯一的输出)我认为您只需要使用set(tuple(sorted(lst)) for lst in itertools.product(...))之类的方法进行过滤即可。 - Volatility
@Volatility,是否也可以添加这些组合:(0.5, 1), (0.5, 5), (0.5, 8), (4, 1), (4, 5), (4, 8) - Reman
这个解决方案的问题在于,如果我们将列表的列表传递给产品方法,它将无法工作。我们应该只给它分离的列表,并且只有在这种情况下它才能返回乘积。如果我错了,请纠正我。 - Pedram
@Pedram 没错。如果你只有一个列表的列表,那么你需要使用 * 将其解包成单独的参数(参见这里)。 - Volatility

28

这可以通过使用列表推导式而不需要任何导入来实现。以您的示例为例:

first = [1, 5, 8]
second = [0.5, 4]

combined = [(f,s) for f in first for s in second]

print(combined)
# [(1, 0.5), (1, 4), (5, 0.5), (5, 4), (8, 0.5), (8, 4)]

这应该是当前Python的最佳答案。我可能错了,但我认为原来的最佳答案是针对Python 2的 - 或许像这个答案这样的列表推导式当时还不可能。 - msm1089
2
我不同意@msm1089的观点,使用列表推导式的解决方案只适用于已知且数量较少的原始列表。相反,itertools方法可以涵盖任意数量的列表,例如itertools.product(*my_lists)。这更加通用,有时是必要的。 - Cedric Druck
实际上,我同意你的看法@CedricDruck。最常见的方法是使用itertools。但是,如果像你说的那样,只有少量的小列表,那么列表推导可能更好。 - msm1089
好观点,@CedricDruck,两种方法都有其适用的场合。虽然如此,我认为大多数人都希望避免再次导入,特别是在他们可以不这样做时。OP在这里提出的具体问题是一小部分已知列表,因此答案非常适用。 - SpinUp __ A Davis

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