У меня есть список кортежей из 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])
Есть ли встроенная функция, которая делает это?
Ответы:
zip
это свой обратный! При условии, что вы используете специальный * оператор.Это работает путем вызова
zip
аргументов:... за исключением того, что аргументы передаются
zip
напрямую (после преобразования в кортеж), поэтому не нужно беспокоиться о том, что количество аргументов становится слишком большим.источник
zip([], [])
таким способом не получится[], []
. Это получает вас[]
. Если только ...zip
работает точно так же в Python 3 за исключением того, что он возвращает итератор вместо списка. Чтобы получить тот же вывод, что и выше, вам просто нужноlist(zip(*[('a', 1), ('b', 2), ('c', 3), ('d', 4)]))
[('a', 'b', 'c', 'd'), (1, 2, 3, 4)]
list
с хорошо. Но если вы попытаетесь реализовать полный результат все сразу (поlist
ifying результатаzip
), вы можете использовать много памяти (потому что все , чтоtuple
ей необходимо создать сразу). Если вы можете просто перебрать результатzip
безlist
ifying, вы сэкономите много памяти. Единственное другое беспокойство - если вход имеет много элементов; цена его заключается в том, что он должен распаковать их все как аргументы иzip
должен будет создать и сохранить итераторы для всех них. Это реальная проблема только с очень длиннымиlist
символами (например, сотнями тысяч элементов или более).Вы могли бы также сделать
Это должно масштабироваться лучше. Особенно, если Python преуспевает в том, чтобы не расширять список пониманий без необходимости.
(Между прочим, он создает 2-кортеж (пару) списков, а не список кортежей, как это
zip
делает.)Если генераторы вместо реальных списков в порядке, это будет сделано так:
Генераторы не просматривают список, пока вы не запросите каждый элемент, но, с другой стороны, они сохраняют ссылки на исходный список.
источник
zip(*x)
версия.zip(*x)
требуется только один проход через цикл и не использует элементы стека.zip
если в сценарии использования транспонированные данные используются и сразу отбрасываются, тогда как исходные списки остаются в памяти гораздо дольше.Если у вас есть списки, которые не имеют одинаковую длину, вы можете не использовать zip согласно ответу Патрика. Это работает:
Но со списками разной длины zip усекает каждый элемент до длины самого короткого списка:
Вы можете использовать карту без функции, чтобы заполнить пустые результаты с помощью None:
Хотя zip () немного быстрее.
источник
izip_longest
zip_longest
для пользователей python3.Мне нравится использовать
zip(*iterable)
(это фрагмент кода, который вы ищете) в моих программах, так:Я нахожу
unzip
более читабельным.источник
Дает кортеж списков, как в вопросе.
Распаковывает два списка.
источник
Наивный подход
отлично работает для конечных итерируемых (например, последовательностей типа
list
/tuple
/str
) (потенциально бесконечных) итерируемых, которые можно проиллюстрировать какгде
n in ℕ
,a_ij
соответствует -омуj
элементуi
-й итерируемой,и после подачи заявления
transpose_finite_iterable
мы получаемPython пример такого случая , когда
a_ij == j
,n == 2
Но мы не можем использовать
transpose_finite_iterable
снова, чтобы вернуться к структуре оригинала,iterable
потому чтоresult
это бесконечная итерация конечных итераций (tuple
в нашем случае s):Итак, как мы можем справиться с этим делом?
... и вот идет
deque
После того, как мы посмотрим на документы по
itertools.tee
функциям , есть рецепт Python, который с некоторыми изменениями может помочь в нашем случаеДавайте проверим
Синтез
Теперь мы можем определить общую функцию для работы с итерациями итерируемых, одни из которых конечны, а другие потенциально бесконечны, используя
functools.singledispatch
декоратор, такой каккоторый можно рассматривать как свой собственный обратный (математики называют этот вид функций «инволюциями» ) в классе бинарных операторов над конечными непустыми итерациями.
В качестве бонуса
singledispatch
мы можем обрабатыватьnumpy
массивы, такие кака затем использовать его как
Запись
Поскольку
transpose
возвращает итераторы , и если кто - то хочет иметьtuple
вlist
с , как в OP - это может быть сделано дополнительно сmap
встроенной функцией , какРеклама
Я добавил обобщенное решение для
lz
пакета из0.5.0
версии, которая может быть использована какPS
Не существует решения (по крайней мере, очевидного) для обработки потенциально бесконечно повторяемых и потенциально бесконечно повторяемых, но этот случай менее распространен.
источник
Это всего лишь другой способ сделать это, но он мне очень помог, поэтому я пишу это здесь:
Имея эту структуру данных:
В результате чего:
На мой взгляд, более питонный способ разархивировать его и вернуться к оригиналу:
Но это возвращает кортеж, поэтому, если вам нужен список, вы можете использовать:
источник
Рассмотрите возможность использования more_itertools.unzip :
источник
Поскольку он возвращает кортежи (и может использовать тонны памяти),
zip(*zipped)
уловка кажется мне более умной, чем полезной.Вот функция, которая на самом деле даст вам обратную сторону zip.
источник
Ни один из предыдущих ответов эффективно не обеспечивает требуемый вывод, который является кортежем списков , а не списком кортежей . Для первого вы можете использовать
tuple
сmap
. Вот разница:Кроме того, большинство предыдущих решений предполагает Python 2.7, где
zip
возвращает список, а не итератор.Для Python 3.x вам нужно будет передать результат в функцию, например,
list
илиtuple
исчерпать итератор. Для итераторов с эффективным использованием памяти вы можете опустить внешниеlist
иtuple
вызовы соответствующих решений.источник
Хотя
zip(*seq)
это очень полезно, оно может быть неподходящим для очень длинных последовательностей, поскольку оно создаст кортеж значений для передачи. Например, я работал с системой координат с более чем миллионом записей и нашел, что ее создание значительно быстрее последовательности напрямую.Общий подход будет выглядеть примерно так:
Но, в зависимости от того, что вы хотите сделать с результатом, выбор коллекции может иметь большое значение. В моем реальном случае использования наборы без внутреннего цикла заметно быстрее всех других подходов.
И, как уже отмечали другие, если вы делаете это с наборами данных, возможно, имеет смысл вместо этого использовать коллекции Numpy или Pandas.
источник
В то время как числовые массивы и панды могут быть предпочтительнее, эта функция имитирует поведение
zip(*args)
при вызове какunzip(args)
.Позволяет передавать генераторы так,
args
как они перебирают значения. Украситьcls
и / илиmain_cls
микроуправлять контейнером инициализации.источник