Отдельная комбинация из двух отдельных списков, сохраняющих соответствие / зависимость друг от друга

#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 отражается на выходных перестановках.