Python объединение списков различной длины - PullRequest
2 голосов
/ 15 марта 2020

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

selected_cells = [[[1],[2],[3]], [[4],[5],[6]], [[7],[8]]]

Мой ожидаемый результат будет [[1,4,7], [2,5,8], [3,6]]

Я написал следующую функцию

def merge(lst1, lst2): 
  print('Merging', lst1, 'and', lst2)
  return [(sub + [lst2[i][-1]]) for i, sub in enumerate(lst1) if i < len(lst2)]

for idx, cell in enumerate(selected_cells):
  if idx < (len(selected_cells)-1):
    print(idx)
    selected_cells[0] = merge(selected_cells[0], selected_cells[idx+1])
    print('Output', selected_cells[0])

Однако это выводит [[1, 4, 7], [2, 5, 8]]

Я чувствую, что упускаю что-то простое здесь, и это сводит меня с ума. Любая помощь будет оценена

Ответы [ 2 ]

1 голос
/ 15 марта 2020

Вы можете использовать zip_longest, как указано в комментариях, потому что zip остановится на самой короткой итерации, например:

from itertools import zip_longest

selected_cells = [[[1],[2],[3]], [[4],[5],[6]], [[7],[8]]]

output = [
    [cell[0] for cell in row if cell is not None] 
    for row in zip_longest(*selected_cells) 
]
print(output)
>>> [[1, 4, 7], [2, 5, 8], [3, 6]]
1 голос
/ 15 марта 2020

Как написано в комментариях, вы можете использовать zip_longest из itertools модуля.

>>> selected_cells = [[[1],[2],[3]], [[4],[5],[6]], [[7],[8]]]
>>> from itertools import zip_longest
>>> L = list(zip_longest(*selected_cells))
>>> L
[([1], [4], [7]), ([2], [5], [8]), ([3], [6], None)]

А затем сгладить кортежи и удалить значения None:

>>> [[x[0] for x in t if x] for t in L]
[[1, 4, 7], [2, 5, 8], [3, 6]]

Другим вариантом является использование сгиба (functools.reduce):

>>> selected_cells = [[[1],[2],[3]], [[4],[5],[6]], [[7],[8]]]
>>> import functools
>>> functools.reduce(lambda acc, x: [acc[i] + (x[i] if i < len(x) else []) for i in range(len(acc))], selected_cells)
[[1, 4, 7], [2, 5, 8], [3, 6]]

Возможно, это менее интуитивно понятно.

...