Zip с выводом списка вместо кортежа

Каков самый быстрый и элегантный способ создания списка списков из двух списков?

у меня есть

In [1]: a=[1,2,3,4,5,6]

In [2]: b=[7,8,9,10,11,12]

In [3]: zip(a,b)
Out[3]: [(1, 7), (2, 8), (3, 9), (4, 10), (5, 11), (6, 12)]

И я хотел бы иметь

In [3]: some_method(a,b)
Out[3]: [[1, 7], [2, 8], [3, 9], [4, 10], [5, 11], [6, 12]]

Я думал об использовании карты вместо zip, но я не знаю, есть ли какой-то стандартный библиотечный метод для использования в качестве первого аргумента.

Я могу определить для этого свою собственную функцию и использовать карту, мой вопрос в том, реализовано ли что-то уже. Нет также является ответом.


person Jan Vorcak    schedule 04.12.2011    source источник
comment
Вам действительно нужны списки? Что вы собираетесь делать с результатами?   -  person Karl Knechtel    schedule 04.12.2011
comment
Примером может служить sklearn, где много раз данные должны быть организованы таким образом.   -  person tumultous_rooster    schedule 01.12.2013


Ответы (7)


Если вы архивируете более 2 списков (или даже только 2, если на то пошло), удобочитаемым способом будет:

[list(a) for a in zip([1,2,3], [4,5,6], [7,8,9])]

Это использует понимание списка и преобразует каждый элемент в списке (кортежи) в списки.

person D K    schedule 04.12.2011

Ты сам почти нашел ответ. Не используйте map вместо zip. Используйте map И zip.

Вы можете использовать карту вместе с zip для элегантного и функционального подхода:

list(map(list, zip(a, b)))

zip возвращает список кортежей. map(list, [...]) вызывает list для каждого кортежа в списке. list(map([...]) превращает объект карты в читаемый список.

person Eldamir    schedule 07.12.2016
comment
неудачное решение заставить операции коллекций python 3 возвращать generator налагает здесь стоимость двойного list. - person WestCoastProjects; 01.06.2019

Мне нравится элегантность функции zip, но использование функции itemgetter() в модуле оператора кажется намного быстрее. Я написал простой скрипт, чтобы проверить это:

import time
from operator import itemgetter

list1 = list()
list2 = list()
origlist = list()
for i in range (1,5000000):
        t = (i, 2*i)
        origlist.append(t)

print "Using zip"
starttime = time.time()
list1, list2 = map(list, zip(*origlist))
elapsed = time.time()-starttime
print elapsed

print "Using itemgetter"
starttime = time.time()
list1 = map(itemgetter(0),origlist)
list2 = map(itemgetter(1),origlist)
elapsed = time.time()-starttime
print elapsed

Я ожидал, что zip будет быстрее, но метод itemgetter выигрывает с большим отрывом:

Using zip
6.1550450325
Using itemgetter
0.768098831177
person kslnet    schedule 10.03.2014
comment
Это перенос того, что пытается сделать ОП. Не могли бы вы обновить свой пост, чтобы отразить это? То есть OP преобразует два списка в список или произвольное количество пар. Вы конвертируете произвольное количество пар в пару списков. - person Mad Physicist; 20.07.2016
comment
С какой версией Python это измеряется? - person Moberg; 15.09.2016
comment
Не помню, было больше двух лет назад, но скорее всего 2,6 или 2,7. Я предполагаю, что вы можете скопировать код и попробовать его на своей версии/платформе. - person kslnet; 15.09.2016
comment
python 2 zip создает настоящий список. Это замедляет работу. Тогда попробуйте заменить zip на itertools.izip. - person Jean-François Fabre; 18.11.2017
comment
В Python 3.5 zip занимает 3,5 секунды, а itemgetter — 0,10 секунды. Для тех, кто любит понимание списка, list1 = [x[0] for x in origlist] работает так же хорошо, как list1 = map(itemgetter(0), origlist). - person Elias Strehle; 09.11.2018

Обычно я не люблю использовать лямбда, но...

>>> a = [1, 2, 3, 4, 5]
>>> b = [6, 7, 8, 9, 10]
>>> c = lambda a, b: [list(c) for c in zip(a, b)]
>>> c(a, b)
[[1, 6], [2, 7], [3, 8], [4, 9], [5, 10]]

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

>>> d = lambda a, b: map(list, zip(a, b))
>>> d(a, b)
[[1, 6], [2, 7], [3, 8], [4, 9], [5, 10]]

Однако карта считается непитоновской и должна использоваться только для настройки производительности.

person Ceasar Bautista    schedule 04.12.2011
comment
Что здесь добавляет lambda? Можно просто написать выражение вместо вызова функции (это на самом деле не сложно), и даже если вам нужна функция для нее, ее можно безболезненно определить в двух строках (одна, если ваша клавиша возврата не работает или вы сошли с ума) . map, с другой стороны, совершенно нормально, если первый аргумент будет простой функцией (в отличие от lambda). - person ; 04.12.2011
comment
Ну, он попросил функцию. Но я согласен - наверное, лучше просто заплатить за лишнюю строку. Что касается карты, я считаю, что понимание списка почти всегда яснее. - person Ceasar Bautista; 04.12.2011
comment
Я бы рекомендовал map вместо lambda. так map(list, zip(a,b)). Понимание списков может быть немного яснее, но карта должна быть быстрее (не проверено) - person inspectorG4dget; 04.12.2011
comment
Я имею в виду, опять же, если OP нужна скорость, карта — это то, что нужно. Но в целом, и в Python особенно, подчеркивайте удобство чтения, а не скорость (иначе вы погрузитесь в преждевременную оптимизацию). - person Ceasar Bautista; 04.12.2011

Как насчет этого?

>>> def list_(*args): return list(args)

>>> map(list_, range(5), range(9,4,-1))
[[0, 9], [1, 8], [2, 7], [3, 6], [4, 5]]

Или еще лучше:

>>> def zip_(*args): return map(list_, *args)
>>> zip_(range(5), range(9,4,-1))
[[0, 9], [1, 8], [2, 7], [3, 6], [4, 5]]
person Broseph    schedule 02.11.2013
comment
Это кажется мне лучшим ответом, чем остальные, поскольку здесь мы сокращаем один шаг, не выполняя zip и напрямую создавая список. Потрясающий - person Akshay Hazari; 02.11.2015

Использование numpy

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

import numpy as np 
a = b = range(10)
zipped = zip(a,b)
# result = np.array(zipped).tolist() Python 2.7
result = np.array(list(zipped)).tolist()
Out: [[0, 0],
 [1, 1],
 [2, 2],
 [3, 3],
 [4, 4],
 [5, 5],
 [6, 6],
 [7, 7],
 [8, 8],
 [9, 9]]

В противном случае, пропустив функцию zip, вы можете напрямую использовать np.dstack :

np.dstack((a,b))[0].tolist()
person G M    schedule 12.09.2018
comment
Первый пример у меня не работает, np.array(zipped) это array(<class 'zip'>, dtype=object), помещая его в список, просто возвращайте zip - person Jean Bouvattier; 29.06.2021
comment
однако np.array(list(zipped)).tolist() будет работать - person Jean Bouvattier; 29.06.2021
comment
@JeanBouvattier спасибо за ваш комментарий, да, это потому, что в Python 3 zip больше не список, а zip-объект - person G M; 29.06.2021

Понимание списка было бы очень простым решением, я думаю.

a=[1,2,3,4,5,6]

b=[7,8,9,10,11,12]

x = [[i, j] for i, j in zip(a,b)]

print(x)

output : [[1, 7], [2, 8], [3, 9], [4, 10], [5, 11], [6, 12]]
person axai_m    schedule 21.04.2017