Комбинации между двумя списками?

Это было некоторое время, и у меня возникли проблемы с обволакиванием вокруг алгоритма, который я пытаюсь сделать. В принципе, у меня есть два списка и вы хотите получить все комбинации этих двух списков.

Возможно, я не объясню это правильно, поэтому вот пример.

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

вывод в этом случае будет:

1.  A1 B2
2.  B1 A2

Сложная часть: у меня может быть больше элементов в переменной "name", чем в переменной "number" (число всегда будет равно или меньше переменной name).

Я запутался, как делать все комбинации (вложенные в цикл?) и еще больше путать с логикой, чтобы переместить элементы в переменной имени в том случае, если в списке есть больше элементов, чем в списке номеров.

Я не лучший программист, но думаю, что могу дать ему шанс, если кто-то может помочь мне прояснить логику/алгоритм, чтобы достичь этого. Поэтому я просто застрял на вложенных циклах.

Update:

Здесь вывод с тремя переменными и двумя номерами:

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

Ответ 1

Предположим, что len(list1) >= len(list2). Тогда вам нужно взять все перестановки длины len(list2) из list1 и сопоставить их с элементами из list2. В питоне:

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

Ответ 2

Самый простой способ - использовать itertools.product:

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

Ответ 3

Может быть проще, чем простой выше:

>>> a = ["foo", "bar"]
>>> b = [1, 2, 3]
>>> [(x,y) for x in a for y in b]
[('foo', 1), ('foo', 2), ('foo', 3), ('bar', 1), ('bar', 2), ('bar', 3)]

без какого-либо импорта

Ответ 4

Я искал список, умноженный на себя только с уникальными комбинациями, который предоставляется как эта функция.

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

Ответ 5

Возможно, вы захотите попробовать однострочное расписание:

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

Ответ 6

небольшое улучшение ответа от 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)]

ссылка из этой ссылки

Ответ 7

Без itertools

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

Ответ 8

Отвечая на вопрос "дано два списка, найдите все возможные перестановки пар одного элемента из каждого списка" и используя базовые функциональные возможности 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']]

Ответ 9

Или ответ KISS для коротких списков:

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

Не так производительно, как itertools, но вы используете python, поэтому производительность уже не ваша главная задача...

Мне нравятся все остальные ответы тоже!

Ответ 10

Лучший способ узнать все комбинации для большого количества списков:

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

Ответ 11

Лучшие ответы на этот вопрос подходят только для определенных длин списков, которые предоставляются.

Здесь версия, которая работает для любой длины ввода. Это также делает алгоритм понятным с точки зрения математических концепций комбинации и перестановки.

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