Jaki jest najszybszy i najbardziej elegancki sposób tworzenia list z dwóch list?
mam
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)]
I chciałbym mieć
In [3]: some_method(a,b)
Out[3]: [[1, 7], [2, 8], [3, 9], [4, 10], [5, 11], [6, 12]]
Myślałem o użyciu map zamiast zip, ale nie wiem, czy istnieje jakaś standardowa metoda biblioteczna, którą można umieścić jako pierwszy argument.
Mogę do tego zdefiniować własną funkcję i użyć mapy. Moje pytanie brzmi, czy coś jest już zaimplementowane. Nie jest również odpowiedzią.
Odpowiedzi:
Jeśli pakujesz więcej niż 2 listy (lub nawet tylko 2), czytelnym sposobem byłoby:
[list(a) for a in zip([1,2,3], [4,5,6], [7,8,9])]
Używa to wyrażeń listowych i konwertuje każdy element na liście (krotki) na listy.
źródło
Prawie znałeś odpowiedź. Nie używaj
map
zamiastzip
. Użyjmap
ANDzip
.Możesz użyć mapy wraz z zipem, aby uzyskać eleganckie i funkcjonalne podejście:
list(map(list, zip(a, b)))
zip
zwraca listę krotek.map(list, [...])
wywołujelist
każdą krotkę na liście.list(map([...])
zamienia obiekt mapy w czytelną listę.źródło
generator
nakłada tutaj koszt podwójnegolist
.Uwielbiam elegancję funkcji zip, ale użycie funkcji itemgetter () w module operatora wydaje się być znacznie szybsze. Napisałem prosty skrypt, aby to przetestować:
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
Spodziewałem się, że zip będzie szybszy, ale metoda itemgetter wygrywa z daleka:
Using zip 6.1550450325 Using itemgetter 0.768098831177
źródło
zip
tworzy prawdziwą listę. To spowalnia wszystko. Spróbuj wymienićzip
zitertools.izip
potem.list1 = [x[0] for x in origlist]
działa równie dobrzelist1 = map(itemgetter(0), origlist)
.Generalnie nie lubię używać lambdy, ale ...
>>> 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]]
Jeśli potrzebujesz dodatkowej prędkości, mapa jest nieco szybsza:
>>> d = lambda a, b: map(list, zip(a, b)) >>> d(a, b) [[1, 6], [2, 7], [3, 8], [4, 9], [5, 10]]
Jednak mapa jest uważana za niepytoniczną i powinna być używana tylko do dostrajania wydajności.
źródło
lambda
tu dodaje? Można po prostu napisać wyrażenie zamiast wywoływać funkcję (to naprawdę nie jest skomplikowane), a nawet jeśli ktoś chce dla niej funkcję, można ją bezboleśnie zdefiniować w dwóch wierszach (jeden, jeśli klucz powrotu jest uszkodzony lub jesteś szalony) .map
z drugiej strony jest w porządku, jeśli pierwszy argument byłby zwykłą funkcją (w przeciwieństwie do alambda
).map
ponadlambda
. takmap(list, zip(a,b))
. Listy mogą być trochę jaśniejsze, ale mapa powinna być szybsza (nieprzetestowana)Co powiesz na to?
>>> def list_(*args): return list(args) >>> map(list_, range(5), range(9,4,-1)) [[0, 9], [1, 8], [2, 7], [3, 6], [4, 5]]
Albo jeszcze lepiej:
>>> def zip_(*args): return map(list_, *args) >>> zip_(range(5), range(9,4,-1)) [[0, 9], [1, 8], [2, 7], [3, 6], [4, 5]]
źródło
Używanie numpy
Definicja elegancji może być dość wątpliwa, ale jeśli pracujesz
numpy
nad tworzeniem tablicy i jej konwersją na listę (w razie potrzeby ...) może być bardzo praktyczna, nawet jeśli nie jest tak wydajna w porównaniu z użyciemmap
funkcji lub rozumienia list.import numpy as np a = b = range(10) zipped = zip(a,b) result = np.array(zipped).tolist() Out: [[0, 0], [1, 1], [2, 2], [3, 3], [4, 4], [5, 5], [6, 6], [7, 7], [8, 8], [9, 9]]
W przeciwnym razie pomijanie
zip
funkcji, której możesz użyć bezpośrednionp.dstack
:np.dstack((a,b))[0].tolist()
źródło
Myślę, że rozumienie listy byłoby bardzo prostym rozwiązaniem.
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]]
źródło