Zip dengan keluaran daftar, bukan tupel


94

Apa cara tercepat dan paling elegan untuk melakukan daftar daftar dari dua daftar?

saya sudah

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)]

Dan saya ingin memilikinya

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

Saya sedang berpikir untuk menggunakan peta daripada zip, tapi saya tidak tahu apakah ada beberapa metode perpustakaan standar untuk dimasukkan sebagai argumen pertama.

Saya dapat mendefinisikan fungsi saya sendiri untuk ini, dan menggunakan peta, pertanyaan saya adalah apakah sudah ada yang diterapkan. Tidak juga merupakan jawaban.


1
Nah, apakah Anda benar - benar membutuhkan daftar? Apa yang akan Anda lakukan dengan hasilnya?
Karl Knechtel

14
Contohnya adalah sklearn, di mana banyak kali data harus diatur dengan cara ini.
tumultous_rooster

Jawaban:


101

Jika Anda membuat zip lebih dari 2 daftar (atau bahkan hanya 2, dalam hal ini), cara yang dapat dibaca adalah:

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

Ini menggunakan pemahaman daftar dan mengubah setiap elemen dalam daftar (tupel) menjadi daftar.


54

Anda sendiri hampir mendapatkan jawabannya. Jangan gunakan mapsebagai gantinya zip. Gunakan map DAN zip .

Anda dapat menggunakan peta bersama dengan zip untuk pendekatan yang elegan dan fungsional:

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

zipmengembalikan daftar tupel. map(list, [...])panggilan listpada setiap tupel dalam daftar. list(map([...])mengubah objek peta menjadi daftar yang dapat dibaca.


Keputusan malang untuk membuat operasi koleksi python 3 kembali generatormembebankan biaya ganda listdi sini.
StephenBoesch

15

Saya suka keanggunan fungsi zip, tetapi menggunakan fungsi itemgetter () di modul operator tampaknya jauh lebih cepat. Saya menulis skrip sederhana untuk menguji ini:

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

Saya berharap zip menjadi lebih cepat, tetapi metode itemgetter menang jauh:

Using zip
6.1550450325
Using itemgetter
0.768098831177

2
Ini adalah transpos dari apa yang OP coba lakukan. Bisakah Anda memperbarui posting Anda untuk mencerminkan itu? Yaitu, OP mengubah dua daftar menjadi daftar atau jumlah pasangan yang berubah-ubah. Anda mengubah jumlah sembarang pasangan menjadi sepasang daftar.
Fisikawan Gila

Dengan versi python apa ini diukur?
Moberg

Saya tidak ingat, itu lebih dari dua tahun yang lalu, tetapi kemungkinan besar 2.6 atau 2.7. Saya membayangkan Anda dapat menyalin kode dan mencobanya pada versi / platform Anda sendiri.
kslnet

2
python 2 zipmembuat daftar nyata. Itu memperlambat segalanya. Coba ganti zipdengan itertools.izipitu.
Jean-François Fabre

Di Python 3.5, zip membutuhkan 3,5 detik dan itemgetter membutuhkan 0,10 detik. Bagi mereka yang menyukai pemahaman daftar, juga list1 = [x[0] for x in origlist]berfungsi dengan baik list1 = map(itemgetter(0), origlist).
Elias Strehle

3

Saya biasanya tidak suka menggunakan lambda, tapi ...

>>> 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]]

Jika Anda membutuhkan kecepatan ekstra, petakan sedikit lebih cepat:

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

Namun, map dianggap unpythonic dan hanya boleh digunakan untuk penyetelan performa.


4
Apa yang lambdaditambahkan di sini? Seseorang bisa saja menulis ekspresi alih-alih memanggil suatu fungsi (sebenarnya tidak rumit), dan bahkan jika seseorang menginginkan fungsi untuknya, itu dapat didefinisikan tanpa rasa sakit dalam dua baris (satu jika kunci kembali Anda rusak atau Anda gila) . mapdi sisi lain baik-baik saja jika argumen pertama akan menjadi fungsi biasa (sebagai lawan a lambda).

1
Yah dia minta fungsi. Tapi saya setuju-- mungkin lebih baik hanya membayar baris ekstra. Mengenai peta, saya yakin pemahaman daftar hampir selalu lebih jelas.
Ceasar Bautista

1
Saya akan merekomendasikan maplebih lambda. jadi map(list, zip(a,b)). Pemahaman daftar mungkin sedikit lebih jelas, tetapi peta harus lebih cepat (belum teruji)
inspectorG4dget

Maksud saya, sekali lagi, jika OP membutuhkan kecepatan, peta adalah jalan yang harus ditempuh. Tetapi secara umum, dan khususnya di Python, menekankan keterbacaan daripada kecepatan (jika tidak, Anda akan masuk ke dalam pengoptimalan prematur).
Ceasar Bautista

3

Bagaimana dengan ini?

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

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

Atau bahkan lebih baik:

>>> def zip_(*args): return map(list_, *args)
>>> zip_(range(5), range(9,4,-1))
[[0, 9], [1, 8], [2, 7], [3, 6], [4, 5]]

Bagi saya itu jawaban yang lebih baik daripada yang lain karena di sini kami mengurangi satu langkah dengan tidak melakukan zip dan langsung membuat daftar. Luar biasa
Akshay Hazari

2

Menggunakan numpy

Definisi keanggunan bisa sangat dipertanyakan tetapi jika Anda bekerja dengan numpypembuatan array dan konversinya ke daftar (jika diperlukan ...) bisa sangat praktis meskipun tidak begitu efisien dibandingkan menggunakan mapfungsi atau pemahaman daftar.

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]]

Jika tidak, lewati zipfungsi yang dapat Anda gunakan secara langsung np.dstack:

np.dstack((a,b))[0].tolist()

1

Pemahaman daftar akan menjadi solusi yang sangat sederhana.

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]]
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.