#python #list #combinations #permutation #itertools
#python #Список #комбинации #перестановка #itertools
Вопрос:
У меня есть два списка из 5 элементов. Я хочу использовать itertools, или код python возвращает список из 5 элементов, которые состоят из всех перестановок списка, только путем замены элементов двух списков с одинаковым индексом.
Например, если A = [1,2,3,4,5]
и B = [a,b,c,d,e]
, я хочу, чтобы он возвращал следующий список списков, C:
Случай, когда никакие элементы A
не заменяются на B
:
[1,2,3,4,5]
Случай, когда все индексы в A
заменяются на B
:
[a,b,c,d,e]
Случаи, когда только один элемент in A
заменяется элементом in B
с соответствующим индексом:
[a, 2, 3, 4, 5]
[1, b, 3, 4, 5]
[1, 2, c, 4, 5]
[1, 2, 3, d, 5]
[1, 2, 3, 4, e]
Случаи, когда два элемента in A
заменяются элементом in B
с соответствующим индексом (ПРИМЕЧАНИЕ: это могут быть любые два элемента, два элемента не обязательно должны быть смежными):
[a, b, 3, 4, 5]
[1, b, c, 4, 5]
[1, 2, c, d, 5]
… и т. д…
[a, 2, 3, 4, e]
[1, b, 3, c, 5]
… и т. д…
Случаи, когда заменяются 3 элемента (опять же, это могут быть любые 3 элемента):
[a, b, c, 4, 5]
[1, b, c, d, 5]
… и т. д…
Случаи, когда заменяются 4 элемента (любые 4 элемента):
[a, b, c, d, 5]
[a, 2, c, d, e]
[a, b, c, 4, e]
…и т.д…
Я думал, что это будет просто с помощью itertools, но я столкнулся с проблемой при создании этого списка списков.
Комментарии:
1. Вы уверены, что имеете в виду здесь перестановки ? Потому что в ваших примерах порядок элементов списка никогда не меняется!
Ответ №1:
Вот один лайнер для этого:
from itertools import product
A = [1,2,3,4,5]
B = ['a','b','c','d','e']
n = len(A)
out = [[(A if x[i] else B)[i] for i in range(n)] for x in product([0,1], repeat=n)]
или (немного) более pythonic:
out = [[(A if y else B)[i] for i,y in enumerate(x)] for x in product([0,1], repeat=n)]
Объяснение:
x
охватывает все возможности выбора i
‘-го элемента в любом A
или B
.
Если это слишком загадочно для вас, то вот расширенная версия:
out = []
for x in product([0,1], repeat=n):
l = []
for i in range(n):
if x[i]:
l.append(A[i])
else:
l.append(B[i])
out.append(l)
Комментарии:
1. Прохладный. Но однострочный, возможно, слишком
dense
для непосвященных …. (простой цикл for может помочь?)2. Добавлена многострочная версия 🙂
3. Спасибо, ТИЛ. Лучше однострочный лайнер … 😉
Ответ №2:
Если я возьму ваши примеры и проигнорирую перестановки слов, то вам нужен итератор, который выполняет следующее: учитывая два списка одинаковой длины в качестве входных данных, он возвращает кучу списков, в которых элементы первого списка заменяются соответствующими элементами второго списка; и индексыэлементы, подлежащие замене, представляют собой все комбинации возможных индексов длиной N.
Вероятно, что-то либо с функцией генератора, либо с классом итератора…
def get_list_replacement_combinations(list_a, list_b):
# skipping some checks, like lists having same length
N = len(list_a)
for num_replaced_items in range(N 1):
new_list = list(list_a) # make a copy so we don't mess up the original
for combination in itertools.combinations(range(N), r=num_replaced_items):
for index in combination:
new_list[index] = list_b[index]
yield new_list
Я придумал это на лету и не тестировал, поэтому могут быть ошибки, но это определенно общая идея. Вероятно, портит случай «длины 0» замененных элементов…