两个名单之间的组合?

时间:2012-10-17 13:16:32

标签: python algorithm list combinations

已经有一段时间了,我无法绕过我试图制作的算法。基本上,我有两个列表,并希望获得两个列表的所有组合。

我可能没有解释它是正确的所以这是一个例子。

name = 'a', 'b'
number = 1, 2

这种情况下的输出是:

1.  A1 B2
2.  B1 A2

棘手的部分是“name”变量中的项目可能比“number”变量中的项目多(数字将始终等于或小于名称变量)。

我很困惑如何进行所有组合(嵌套for循环?),如果名称中的项目多于数字中的项目,则更加混淆逻辑以移动名称变量中的项目列表。

我不是最好的程序员,但是如果有人可以帮助我澄清逻辑/算法来实现这一点,我想我可以试一试。所以我一直坚持使用嵌套for循环。

更新

这是带有3个变量和2个数字的输出:

name = 'a', 'b', 'c'
number = 1, 2

输出:

1.  A1 B2
2.  B1 A2
3.  A1 C2
4.  C1 A2
5.  B1 C2
6.  C1 B2

11 个答案:

答案 0 :(得分:376)

最简单的方法是使用itertools.product

a = ["foo", "melon"]
b = [True, False]
c = list(itertools.product(a, b))
>> [("foo", True), ("foo", False), ("melon", True), ("melon", False)]

答案 1 :(得分:106)

可能比上面最简单的一个简单:

library(purrr)
dfs %>% 
    map2(time, ~cbind(.x, timevar=.y))

没有任何导入

答案 2 :(得分:54)

假设len(list1) >= len(list2)。然后你想要的是从len(list2)获取长度为list1的所有排列,并将它们与list2中的项匹配。在python:

import itertools
list1=['a','b','c']
list2=[1,2]

[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)]]

答案 3 :(得分:14)

我一直在寻找一个仅与其自身相乘的列表,只有这个函数提供了独特的组合。

import itertools
itertools.combinations(list, n_times)

这里摘录自the Python docs on 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

答案 4 :(得分:11)

您可能想尝试单行列表理解:

>>> [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']

答案 5 :(得分:8)

来自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

的参考

答案 6 :(得分:8)

或者是KISS的简短答案:

[(i, j) for i in list1 for j in list2]

性能不如itertools,但您使用的是python,因此性能已不是您的头等要事...

我也喜欢所有其他答案!

答案 7 :(得分:4)

没有itertools

[(list1[i], list2[j]) for i in xrange(len(list1)) for j in xrange(len(list2))]

答案 8 :(得分:4)

回答问题“给出两个列表,找到每个列表中一个项目的所有可能的排列”并使用基本的Python功能(即没有itertools),因此,可以轻松地复制其他编程语言: / p>

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']]

答案 9 :(得分:2)

对此更好的答案仅适用于所提供列表的特定长度。

这是一个适用于任何长度输入的版本。结合组合和排列的数学概念,也使算法更加清晰。

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

答案 10 :(得分:0)

找出大量列表的所有组合的最佳方法是:

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')]