我无法完全理解我尝试实现的算法。我有两个列表,想从这两个列表中获取特定的组合。
这是一个例子。
names = ['a', 'b']
numbers = [1, 2]
这种情况下的输出是:
[('a', 1), ('b', 2)]
[('b', 1), ('a', 2)]
我的名字可能比数字多,即
len(names) >= len(numbers)
。这是一个包含 3 个名字和 2 个数字的示例:
names = ['a', 'b', 'c']
numbers = [1, 2]
输出:
[('a', 1), ('b', 2)]
[('b', 1), ('a', 2)]
[('a', 1), ('c', 2)]
[('c', 1), ('a', 2)]
[('b', 1), ('c', 2)]
[('c', 1), ('b', 2)]
itertools.product
:
a = ["foo", "melon"]
b = [True, False]
c = list(itertools.product(a, b))
>> [("foo", True), ("foo", False), ("melon", True), ("melon", False)]
可能比上面最简单的还要简单:
>>> a = ["foo", "bar"]
>>> b = [1, 2, 3]
>>> [(x,y) for x in a for y in b] # for a list
[('foo', 1), ('foo', 2), ('foo', 3), ('bar', 1), ('bar', 2), ('bar', 3)]
>>> ((x,y) for x in a for y in b) # for a generator if you worry about memory or time complexity.
<generator object <genexpr> at 0x1048de850>
没有任何进口
注意:此答案针对上述特定问题。如果您来自 Google,并且只是在寻找一种在 Python 中获取笛卡尔积的方法,
itertools.product
或简单的列表理解可能就是您正在寻找的 - 请参阅其他答案。
假设
len(list1) >= len(list2)
。然后,您似乎想要的是从 len(list2)
中获取所有长度为 list1
的排列,并将它们与 list2 中的项目相匹配。在 python 中:
import itertools
list1=['a','b','c']
list2=[1,2]
[list(zip(x,list2)) for x in itertools.permutations(list1,len(list2))]
退货
[[('a', 1), ('b', 2)], [('a', 1), ('c', 2)], [('b', 1), ('a', 2)], [('b', 1), ('c', 2)], [('c', 1), ('a', 2)], [('c', 1), ('b', 2)]]
我一直在寻找一个仅由唯一组合乘以自身的列表,它作为此功能提供。
import itertools
itertools.combinations(list, n_times)
这里是 Python 文档的摘录
itertools
这可能会帮助你找到你要找的东西。
Combinatoric generators:
Iterator | Results
-----------------------------------------+----------------------------------------
product(p, q, ... [repeat=1]) | cartesian product, equivalent to a
| nested for-loop
-----------------------------------------+----------------------------------------
permutations(p[, r]) | r-length tuples, all possible
| orderings, no repeated elements
-----------------------------------------+----------------------------------------
combinations(p, r) | r-length tuples, in sorted order, no
| repeated elements
-----------------------------------------+----------------------------------------
combinations_with_replacement(p, r) | r-length tuples, in sorted order,
| with repeated elements
-----------------------------------------+----------------------------------------
product('ABCD', repeat=2) | AA AB AC AD BA BB BC BD CA CB CC CD DA DB DC DD
permutations('ABCD', 2) | AB AC AD BA BC BD CA CB CD DA DB DC
combinations('ABCD', 2) | AB AC AD BC BD CD
combinations_with_replacement('ABCD', 2) | AA AB AC AD BB BC BD CC CD DD
找出大量列表的所有组合的最佳方法是:
import itertools
from pprint import pprint
inputdata = [
['a', 'b', 'c'],
['d'],
['e', 'f'],
]
result = list(itertools.product(*inputdata))
pprint(result)
结果将是:
[('a', 'd', 'e'),
('a', 'd', 'f'),
('b', 'd', 'e'),
('b', 'd', 'f'),
('c', 'd', 'e'),
('c', 'd', 'f')]
或短名单的 KISS 答案:
[(i, j) for i in list1 for j in list2]
性能不如 itertools 但您使用的是 python,因此性能已经不是您最关心的问题...
我也喜欢所有其他答案!
您可能想尝试单行列表理解:
>>> [name+number for name in 'ab' for number in '12']
['a1', 'a2', 'b1', 'b2']
>>> [name+number for name in 'abc' for number in '12']
['a1', 'a2', 'b1', 'b2', 'c1', 'c2']
对 interjay 的答案进行了微小的改进,使结果成为扁平列表。
>>> list3 = [zip(x,list2) for x in itertools.permutations(list1,len(list2))]
>>> import itertools
>>> chain = itertools.chain(*list3)
>>> list4 = list(chain)
[('a', 1), ('b', 2), ('a', 1), ('c', 2), ('b', 1), ('a', 2), ('b', 1), ('c', 2), ('c', 1), ('a', 2), ('c', 1), ('b', 2)]
来自这个link
的参考没有
itertools
作为扁平列表:
[(list1[i], list2[j]) for i in range(len(list1)) for j in range(len(list2))]
或在Python 2中:
[(list1[i], list2[j]) for i in xrange(len(list1)) for j in xrange(len(list2))]
回答“给定两个列表,从每个列表中找到一个项目对的所有可能排列”的问题,并使用基本的 Python 功能(即没有 itertools),因此可以很容易地复制到其他编程语言:
def rec(a, b, ll, size):
ret = []
for i,e in enumerate(a):
for j,f in enumerate(b):
l = [e+f]
new_l = rec(a[i+1:], b[:j]+b[j+1:], ll, size)
if not new_l:
ret.append(l)
for k in new_l:
l_k = l + k
ret.append(l_k)
if len(l_k) == size:
ll.append(l_k)
return ret
a = ['a','b','c']
b = ['1','2']
ll = []
rec(a,b,ll, min(len(a),len(b)))
print(ll)
退货
[['a1', 'b2'], ['a1', 'c2'], ['a2', 'b1'], ['a2', 'c1'], ['b1', 'c2'], ['b2', 'c1']]
更好的答案只适用于所提供的特定长度的列表。
这是一个适用于任何长度输入的版本。它还使算法在组合和排列的数学概念方面变得清晰。
from itertools import combinations, permutations
list1 = ['1', '2']
list2 = ['A', 'B', 'C']
num_elements = min(len(list1), len(list2))
list1_combs = list(combinations(list1, num_elements))
list2_perms = list(permutations(list2, num_elements))
result = [
tuple(zip(perm, comb))
for comb in list1_combs
for perm in list2_perms
]
for idx, ((l11, l12), (l21, l22)) in enumerate(result):
print(f'{idx}: {l11}{l12} {l21}{l22}')
这输出:
0: A1 B2
1: A1 C2
2: B1 A2
3: B1 C2
4: C1 A2
5: C1 B2