Saya memiliki daftar 2-item tupel dan saya ingin mengubahnya menjadi 2 daftar di mana yang pertama berisi item pertama di setiap tuple dan daftar kedua berisi item kedua.
Sebagai contoh:
original = [('a', 1), ('b', 2), ('c', 3), ('d', 4)]
# and I want to become...
result = (['a', 'b', 'c', 'd'], [1, 2, 3, 4])
Apakah ada fungsi bawaan yang melakukan itu?
Jawaban:
zip
adalah kebalikannya sendiri! Asalkan Anda menggunakan operator * khusus.Cara kerjanya adalah dengan menelepon
zip
dengan argumen:... kecuali argumen dilewatkan
zip
secara langsung (setelah dikonversi ke tuple), jadi tidak perlu khawatir jumlah argumen menjadi terlalu besar.sumber
zip([], [])
dengan cara ini tidak akan membantu Anda[], []
. Itu membuat Anda[]
. Jika saja ...zip
bekerja persis sama di Python 3 kecuali bahwa ia mengembalikan iterator, bukan daftar. Untuk mendapatkan output yang sama seperti di atas, Anda hanya perlu membungkus panggilan zip dalam daftar:list(zip(*[('a', 1), ('b', 2), ('c', 3), ('d', 4)]))
akan menampilkan[('a', 'b', 'c', 'd'), (1, 2, 3, 4)]
list
s baik-baik saja. Tetapi jika Anda mencoba untuk mewujudkan hasil penuh sekaligus (denganlist
ifying hasilzip
), Anda mungkin menggunakan banyak memori (karena semua yangtuple
s harus diciptakan sekaligus). Jika Anda hanya bisa mengulangi hasilzip
tanpalist
ifying, Anda akan menghemat banyak memori. Satu-satunya masalah lain adalah jika input memiliki banyak elemen; biayanya adalah itu harus membongkar semuanya sebagai argumen, danzip
akan perlu membuat dan menyimpan iterator untuk semuanya. Ini hanya masalah nyata dengan s yang sangat panjanglist
(pikirkan ratusan ribu elemen atau lebih).Anda juga bisa melakukannya
Ini harus lebih baik skala. Terutama jika Python berhasil tidak memperluas pemahaman daftar kecuali diperlukan.
(Kebetulan, itu membuat 2-tupel (pasangan) daftar, bukan daftar tupel, seperti
zip
halnya.)Jika generator bukan daftar yang sebenarnya ok, ini akan melakukan itu:
Generator tidak menelusuri daftar sampai Anda meminta setiap elemen, tetapi di sisi lain, mereka tetap referensi ke daftar asli.
sumber
zip(*x)
versi.zip(*x)
hanya membutuhkan satu kali melewati loop, dan tidak menggunakan elemen tumpukan.zip
jika use-case adalah bahwa data yang ditransposisikan digunakan dan dibuang segera, sementara daftar aslinya tetap dalam memori lebih lama.Jika Anda memiliki daftar yang panjangnya tidak sama, Anda mungkin tidak ingin menggunakan zip sesuai jawaban Patricks. Ini bekerja:
Tetapi dengan daftar panjang yang berbeda, zip memotong setiap item dengan panjang daftar terpendek:
Anda dapat menggunakan peta tanpa fungsi untuk mengisi hasil kosong dengan Tidak Ada:
zip () sedikit lebih cepat.
sumber
izip_longest
zip_longest
untuk pengguna python3.Saya suka menggunakan
zip(*iterable)
(yang merupakan bagian dari kode yang Anda cari) dalam program saya sebagai berikut:Saya menemukan
unzip
lebih mudah dibaca.sumber
Memberikan beberapa daftar seperti pada pertanyaan.
Buka paket kedua daftar.
sumber
Pendekatan naif
berfungsi dengan baik untuk iterable terbatas (misalnya urutan seperti
list
/tuple
/str
) dari iterables (berpotensi tak terbatas) yang dapat diilustrasikan sepertidimana
n in ℕ
,a_ij
sesuai denganj
elemeni
-th dari iterable,dan setelah mendaftar
transpose_finite_iterable
kita dapatkanContoh python dari kasus seperti itu di mana
a_ij == j
,n == 2
Tetapi kita tidak dapat menggunakan
transpose_finite_iterable
lagi untuk kembali ke struktur asliiterable
karenaresult
iterable iterable terbatas hingga terbatas (tuple
dalam kasus kami):Jadi bagaimana kita bisa menangani kasus ini?
... dan ini dia
deque
Setelah kita melihat pada docs of
itertools.tee
function , ada resep Python yang dengan beberapa modifikasi dapat membantu dalam kasus kitamari kita periksa
Perpaduan
Sekarang kita dapat mendefinisikan fungsi umum untuk bekerja dengan iterables dari iterables yang terbatas dan yang lainnya berpotensi tak terbatas menggunakan
functools.singledispatch
dekorator sepertiyang dapat dianggap sebagai kebalikannya sendiri (ahli matematika menyebut fungsi semacam ini "involusi" ) di kelas operator biner melalui iterables terbatas yang tidak kosong.
Sebagai bonus
singledispatch
kami dapat menanganinumpy
array sepertidan kemudian gunakan seperti
Catatan
Sejak
transpose
kembali iterator dan jika seseorang ingin memilikituple
darilist
s seperti di OP - ini dapat dibuat juga denganmap
built-in fungsi sepertiIklan
Saya telah menambahkan solusi umum ke
lz
paket dari0.5.0
versi yang dapat digunakan sepertiPS
Tidak ada solusi (setidaknya jelas) untuk menangani iterable yang berpotensi tak terbatas dari iterables yang berpotensi tak terbatas, tetapi kasus ini lebih jarang terjadi.
sumber
Ini hanya cara lain untuk melakukannya tetapi itu sangat membantu saya, jadi saya menulisnya di sini:
Memiliki struktur data ini:
Yang menghasilkan:
Cara yang lebih pythonic untuk unzip dan kembali ke aslinya adalah yang ini menurut saya:
Tapi ini mengembalikan tuple jadi jika Anda memerlukan daftar, Anda dapat menggunakan:
sumber
Pertimbangkan untuk menggunakan more_itertools.unzip :
sumber
Karena mengembalikan tupel (dan dapat menggunakan banyak memori),
zip(*zipped)
triknya tampaknya lebih pintar daripada berguna, bagi saya.Inilah fungsi yang benar-benar akan memberi Anda kebalikan dari zip.
sumber
Tidak satu pun dari jawaban sebelumnya yang secara efisien memberikan output yang diperlukan, yang merupakan daftar tuple , bukan daftar tuple . Untuk yang pertama, Anda bisa menggunakannya
tuple
bersamamap
. Inilah perbedaannya:Selain itu, sebagian besar solusi sebelumnya mengasumsikan Python 2.7, di mana
zip
mengembalikan daftar daripada iterator.Untuk Python 3.x, Anda harus meneruskan hasilnya ke fungsi seperti
list
atautuple
untuk menghabiskan iterator. Untuk iterator yang efisien-memori, Anda dapat menghilangkan bagian luarlist
dantuple
meminta solusi masing-masing.sumber
Meskipun
zip(*seq)
sangat berguna, mungkin tidak cocok untuk urutan yang sangat lama karena akan membuat tuple nilai yang akan diteruskan. Misalnya, saya telah bekerja dengan sistem koordinat dengan lebih dari satu juta entri dan merasa lebih cepat untuk membuat urutan langsung.Pendekatan generik akan seperti ini:
Tetapi, tergantung pada apa yang ingin Anda lakukan dengan hasilnya, pilihan koleksi dapat membuat perbedaan besar. Dalam kasus penggunaan saya yang sebenarnya, menggunakan set dan tidak ada loop internal, terasa lebih cepat daripada semua pendekatan lainnya.
Dan, seperti yang telah dicatat orang lain, jika Anda melakukan ini dengan dataset, mungkin masuk akal untuk menggunakan koleksi Numpy atau Pandas sebagai gantinya.
sumber
Sementara numpy arrays dan panda mungkin lebih disukai, fungsi ini meniru perilaku
zip(*args)
ketika dipanggilunzip(args)
.Memungkinkan generator untuk diteruskan karena
args
iterates melalui nilai-nilai. Hiasicls
dan / ataumain_cls
untuk inisialisasi pengelolaan mikro.sumber