#python #itertools
#python #python-itertools
Вопрос:
У меня есть два списка одинаковой длины, которые имеют взаимно однозначное соответствие:
a = [1,2,3,4]
b = [6,7,8,9]
Я хочу найти комбинации этих двух списков по отдельности. Но индексы объединенных элементов должны быть одинаковыми для обоих списков.
Например, если я сделаю:
list(itertools.combinations(a,2))
Я могу получить
[(1,2),(1,3),(1,4),(3,2),(4,2),(4,3)]
Я мог бы получить
[(2,1),(3,1),(4,1),(2,3),(2,4),(3,4)]
тоже потому, что оба одинаковы.
Итак, какую бы комбинацию я ни получил, я хочу, чтобы те же индексы были объединены и для второго списка.
Итак, если
list(itertools.combinations(a,2))
дает мне
[(1,2),(1,3),(1,4),(3,2),(4,2),(4,3)]
затем
list(itertools.combinations(b,2))
должно дать мне
[(6,7),(6,8),(6,9),(8,7),(9,7),(9,8)]
или если
list(itertools.combinations(a,2))
дает мне
[(2,1),(3,1),(4,1),(2,3),(2,4),(3,4)]
затем
list(itertools.combinations(b,2))
должно дать мне
[(7,6),(8,6),(9,6),(7,8),(7,9),(8,9)]
Комментарии:
1.
itertools.combinations
является детерминированным, поэтому он всегда будет давать вам один и тот же результат. Если вы беспокоитесь об этомa
иb
по какой-либо причине не синхронизированы, вы всегда можете выполнить сортировку,zip
отредактировав ее заранее.2. Я думаю, вы ищете
itertools.permutations
Ответ №1:
Вы могли бы генерировать комбинации по индексам, а затем индексировать a и b. Например:
a = [1,2,3,4]
b = [6,7,8,9]
for i0,i1 in itertools.combinations(range(len(a)), 2):
print("{0},{1} --> {2},{3}".format(a[i0],a[i1],b[i0],b[i1]))
1,2 --> 6,7
1,3 --> 6,8
1,4 --> 6,9
2,3 --> 7,8
2,4 --> 7,9
3,4 --> 8,9
Ответ №2:
Вы можете посмотреть на исходный код, чтобы сказать вам, что он работает на основе индекса списка, а не значения списка. Таким образом, хотя выходные данные комбинаций всегда будут одинаковыми для одного и того же списка, изменение порядка списка, очевидно, даст вам другой результат для комбинаций.
Почему бы не сортировать ваш список по мере его передачи, чтобы они всегда находились в порядке возрастания чисел, тем самым решая проблему.
a = [4,3,2,1]
list(combinations(a,2))
[(4, 3), (4, 2), (4, 1), (3, 2), (3, 1), (2, 1)]
list(combinations(sorted(a),2))
[(1, 2), (1, 3), (1, 4), (2, 3), (2, 4), (3, 4)]
https://docs.python.org/3/library/itertools.html#itertools.combinations
Ответ №3:
Из официальной документации по python itertools:
«Комбинации генерируются в лексикографическом порядке сортировки. Итак, если входная итерация отсортирована, комбинированные кортежи будут созданы в отсортированном порядке.»
Таким образом, для отсортированного списка порядок всегда будет идентичным, начиная с первого значения.
Комментарии:
1. да, на самом деле он всегда возвращает упорядоченный список для отсортированного списка ввода, но проблема в том, что я не могу отсортировать список. В любом случае, спасибо за помощь, у меня есть свой ответ.
Ответ №4:
Я не видел, чтобы это предлагалось, но разве вы не можете решить это, выбрав из обоих сразу.
a = [1,2,3,4]
b = [6,7,8,9]
from itertools import combinations
list( combinations(zip(a,b),2))
Это дает:
[((1, 6), (2, 7)),
((1, 6), (3, 8)),
((1, 6), (4, 9)),
((2, 7), (3, 8)),
((2, 7), (4, 9)),
((3, 8), (4, 9))]
Вы можете видеть, что они совпадают по всем спискам.
Ответ №5:
Ключевым моментом здесь является использование itertools.permutations
вместо itertools.combinations
. Вот возможная реализация, которая сэкономит немного времени, вычисляя перестановки за один раз:
import itertools
def isomorphic_permutations(*arrays, **kwargs):
arrays_shape = len(arrays[0])
if any(len(a) != arrays_shape for a in arrays):
raise ValueError("All input arrays should have the same size.")
permutations = list(itertools.permutations(range(arrays_shape), **kwargs))
for array in arrays:
yield ((array[x], array[y]) for x, y in permutations)
Kwarg r
используется для построения перестановки с помощью itertools.permutations(iterable, r=None)
. Это соответствует длинам перестановок. Вот как вы могли бы использовать эту функцию:
a = [7,6,8]
b = [6,7,8]
for permutation in isomorphic_permutations(a, b, r=2):
print(list(permutation))
Которая выведет:
[(7, 6), (7, 8), (6, 7), (6, 8), (8, 7), (8, 6)]
[(6, 7), (6, 8), (7, 6), (7, 8), (8, 6), (8, 7)]
Обратите внимание, как инверсия 6
и 7
отражается на выходных перестановках.