Мне нужно составить список пар из нескольких других списков. Пары будут состоять из значений из одной и той же позиции в каждом списке. Может быть разное количество списков, но каждый список будет иметь одинаковое количество значений. Я думаю, что это не совсем комбинации/перестановки, потому что некоторые значения необходимо повторять.
Проще объяснить на примере:
list_a = [1, 2, 3, 4, 5]
list_b = [6, 7, 8, 9, 10]
list_c = [11, 12, 13, 14, 15]
list_d = [16, 17, 18, 19, 20]
Output required = [(1,6),(6,11),(11,16),(2,7),(7,12),(12,17)....etc]
Результатом не обязательно должен быть список кортежей, но я решил, что что-то подобное будет наиболее разумным. Его можно было бы разделить дальше, чтобы каждый «столбец» пар представлял собой отдельный список, но это не важно.
Я собирался применить грубую силу с помощью циклов, но уверен, что есть способ получше. Я чувствую, что это путь zip и itertools, но я не могу этого понять. Этот пост о кусках одинакового размера был почти таким, но из примера выше вы можете видеть, что мне нужно повторно использовать предыдущее значение в следующей паре. Как разделить список на части одинакового размера?
Это можно сделать с помощью двух вложенных вызовов zip
:
list_a = [1, 2, 3, 4, 5]
list_b = [6, 7, 8, 9, 10]
list_c = [11, 12, 13, 14, 15]
list_d = [16, 17, 18, 19, 20]
lists = [list_a, list_b, list_c, list_d]
output = [y for x in zip(*lists) for y in zip(x, x[1:])]
print(output)
Выход:
[(1, 6), (6, 11), (11, 16), (2, 7), (7, 12), (12, 17), (3, 8), (8, 13), (13, 18), (4, 9), (9, 14), (14, 19), (5, 10), (10, 15), (15, 20)]
Первый вызов zip создает кортежи первого элемента, второго элемента и т. д. каждого списка.
Второй вызов zip создает пары (первый, второй), (второй, третий), (третий, четвертый) и т. д.
вы можете использовать itertools.pairwise
здесь, [pair for row in zip(*lists) for pair in pairwise(row)]
Решение с использованием map
и itertools
import itertools
list_a = [1, 2, 3, 4, 5]
list_b = [6, 7, 8, 9, 10]
list_c = [11, 12, 13, 14, 15]
list_d = [16, 17, 18, 19, 20]
result = list(itertools.chain.from_iterable(map(lambda a,b,c,d:((a,b),(b,c),(c,d)),list_a,list_b,list_c,list_d)))
print(result)
дает результат
[(1, 6), (6, 11), (11, 16), (2, 7), (7, 12), (12, 17), (3, 8), (8, 13), (13, 18), (4, 9), (9, 14), (14, 19), (5, 10), (10, 15), (15, 20)]
Спасибо, Давео, приятно увидеть другие методы решения проблемы и получить подтверждение того, что itertools действительно является возможным способом ее решения! Хотя, похоже, эта опция не может масштабироваться, если количество списков варьируется? Если я правильно понимаю, вам придется добавить дополнительные параметры в лямбда-функцию вручную.
from itertools import *
list_a = [1, 2, 3, 4, 5]
list_b = [6, 7, 8, 9, 10]
list_c = [11, 12, 13, 14, 15]
list_d = [16, 17, 18, 19, 20]
lists = list_a, list_b, list_c, list_d
result = [*chain(*map(pairwise, zip(*lists)))]
print(result)
Ого, спасибо за такой быстрый ответ и чистое решение. Делает именно то, что я хотел, в одной строке кода! Очень признателен.