Сведения о вопросе

MAT

10:27, 1st August, 2020

Теги

python   list   matrix   transpose    

Транспонировать/распаковать функцию (обратная zip)?

Просмотров: 577   Ответов: 6

У меня есть список кортежей из 2 элементов, и я хотел бы преобразовать их в 2 списка, где первый содержит первый элемент в каждом кортеже, а второй список содержит второй элемент.

Например:

original = [('a', 1), ('b', 2), ('c', 3), ('d', 4)]
# and I want to become...
result = (['a', 'b', 'c', 'd'], [1, 2, 3, 4])

Есть ли встроенная функция, которая делает это?



  Сведения об ответе

DAAA

07:19, 10th August, 2020

zip - это его собственная обратная сторона! При условии использования специального оператора*.

>>> zip(*[('a', 1), ('b', 2), ('c', 3), ('d', 4)])
[('a', 'b', 'c', 'd'), (1, 2, 3, 4)]

Как это работает, вызывая zip с аргументами:

zip(('a', 1), ('b', 2), ('c', 3), ('d', 4))

... за исключением того, что аргументы передаются в zip напрямую (после преобразования в кортеж), поэтому нет необходимости беспокоиться о том, что число аргументов становится слишком большим.


  Сведения об ответе

lool

03:26, 9th August, 2020

Вы также могли бы сделать

result = ([ a for a,b in original ], [ b for a,b in original ])

Он должен быть лучше масштабирован. Особенно если Python делает хорошо на том, чтобы не расширять список постижений без необходимости.

(Кстати, это делает 2-кортеж (пара) списков, а не список кортежей, как это делает zip .)

Если генераторы вместо реальных списков в порядке, это будет делать это:

result = (( a for a,b in original ), ( b for a,b in original ))

Генераторы не прогрызают список, пока вы не попросите каждый элемент, но, с другой стороны, они сохраняют ссылки на исходный список.


  Сведения об ответе

PAGE

15:28, 16th August, 2020

Если у вас есть списки разной длины, вы можете не использовать zip в соответствии с ответом Патрика. Эта работа:

>>> zip(*[('a', 1), ('b', 2), ('c', 3), ('d', 4)])
[('a', 'b', 'c', 'd'), (1, 2, 3, 4)]

Но с разными списками длины zip усекает каждый элемент до длины самого короткого списка:

>>> zip(*[('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', )])
[('a', 'b', 'c', 'd', 'e')]

Вы можете использовать функцию map with no для заполнения пустых результатов None:

>>> map(None, *[('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', )])
[('a', 'b', 'c', 'd', 'e'), (1, 2, 3, 4, None)]

Однако zip() немного быстрее.


  Сведения об ответе

$DOLLAR

19:01, 2nd August, 2020

Мне нравится использовать zip(*iterable) (который является частью кода, который вы ищете) в моих программах как таковой:

def unzip(iterable):
    return zip(*iterable)

Я нахожу unzip более читабельным.


  Сведения об ответе

PHPH

11:05, 4th August, 2020

>>> original = [('a', 1), ('b', 2), ('c', 3), ('d', 4)]
>>> tuple([list(tup) for tup in zip(*original)])
(['a', 'b', 'c', 'd'], [1, 2, 3, 4])

Дает кортеж списков, как в вопросе.

list1, list2 = [list(tup) for tup in zip(*original)]

Распаковывает оба списка.


  Сведения об ответе

crush

18:40, 18th August, 2020

Это всего лишь другой способ сделать это но он очень помог мне поэтому я пишу его здесь:

Имея такую структуру данных:

X=[1,2,3,4]
Y=['a','b','c','d']
XY=zip(X,Y)

В результате чего:

In: XY
Out: [(1, 'a'), (2, 'b'), (3, 'c'), (4, 'd')]

Более пифонический способ распаковать его и вернуться к оригиналу это на мой взгляд:

x,y=zip(*XY)

Но это возвращает кортеж так что если вам нужен список вы можете использовать:

x,y=(list(x),list(y))


Ответить на вопрос

Чтобы ответить на вопрос вам нужно войти в систему или зарегистрироваться