如何获取两个列表之间的所有映射?

21 投票
2 回答
2349 浏览
提问于 2025-04-18 02:40

我们有两个列表,A 和 B:

A = ['a','b','c']
B = [1, 2]

有没有一种简单的方法可以在 Python 中创建一个包含所有 A 和 B 之间映射的集合,这个集合的大小是 2 的 n 次方(这里 n 是 A 的长度,比如 2^3=8)?也就是说:

[(a,1), (b,1), (c,1)]
[(a,1), (b,1), (c,2)]
[(a,1), (b,2), (c,1)]
[(a,1), (b,2), (c,2)]
[(a,2), (b,1), (c,1)]
[(a,2), (b,1), (c,2)]
[(a,2), (b,2), (c,1)]
[(a,2), (b,2), (c,2)]

使用 itertools.product,我们可以得到所有的元组:

import itertools as it
P = it.product(A, B)
[p for p in P]

这会得到:

Out[3]: [('a', 1), ('a', 2), ('b', 1), ('b', 2), ('c', 1), ('c', 2)]

2 个回答

11
import itertools as it

A = ['a','b','c']
B = [1, 2]

for i in it.product(*([B]*len(A))):
    print(list(zip(A, i)))

输出:

[('a', 1), ('b', 1), ('c', 1)]
[('a', 1), ('b', 1), ('c', 2)]
[('a', 1), ('b', 2), ('c', 1)]
[('a', 1), ('b', 2), ('c', 2)]
[('a', 2), ('b', 1), ('c', 1)]
[('a', 2), ('b', 1), ('c', 2)]
[('a', 2), ('b', 2), ('c', 1)]
[('a', 2), ('b', 2), ('c', 2)]

不太确定这是否算是很“Python风格”,如果你看看 it.product(*([B]*len(A))),它确实使用了很多Python特有的语言特性。不过,这样写其实有点难懂,不太符合Python的简洁风格……这里的B是根据A的长度重复了n次,然后传递给了product函数。

26

你可以使用 itertools.productzip 来实现这个功能。

from itertools import product
print [zip(A, item) for item in product(B, repeat=len(A))]

输出结果

[[('a', 1), ('b', 1), ('c', 1)],
 [('a', 1), ('b', 1), ('c', 2)],
 [('a', 1), ('b', 2), ('c', 1)],
 [('a', 1), ('b', 2), ('c', 2)],
 [('a', 2), ('b', 1), ('c', 1)],
 [('a', 2), ('b', 1), ('c', 2)],
 [('a', 2), ('b', 2), ('c', 1)],
 [('a', 2), ('b', 2), ('c', 2)]]

product(B, repeat=len(A)) 会生成

[(1, 1, 1),
 (1, 1, 2),
 (1, 2, 1),
 (1, 2, 2),
 (2, 1, 1),
 (2, 1, 2),
 (2, 2, 1),
 (2, 2, 2)]

然后我们从这个生成的结果中取出每一个元素,并用 A 来配对,这样就能得到你想要的输出了。

撰写回答