Bagaimana anda membagi daftar ke merata berukuran potongan?
Saya memiliki daftar panjang sewenang-wenang, dan saya perlu untuk membaginya menjadi potongan ukuran yang sama dan beroperasi pada itu. Ada beberapa cara yang jelas untuk melakukan hal ini, seperti menjaga sebuah meja dan dua daftar, dan ketika kedua daftar mengisi, menambahkannya ke daftar pertama dan kosong kedua daftar untuk putaran berikutnya dari data, tapi ini berpotensi sangat mahal.
Aku bertanya-tanya apakah ada yang punya solusi yang baik untuk ini untuk daftar dari setiap panjang, misalnya menggunakan generator.
Aku sedang mencari sesuatu yang berguna di itertools
tapi aku tidak't menemukan sesuatu yang jelas-jelas berguna. Mungkin've kehilangan itu, meskipun.
Terkait pertanyaan: Apa yang paling "pythonic" cara untuk iterate atas daftar dalam potongan?
Berikut ini's sebuah generator yang menghasilkan potongan yang anda inginkan:
Jika anda're menggunakan Python 2, anda harus menggunakan
xrange()
bukanrange()
:Anda juga dapat hanya menggunakan daftar pemahaman alih-alih menulis fungsi, meskipun itu's merupakan ide yang baik untuk merangkum operasi seperti ini di bernama fungsi sehingga kode anda lebih mudah untuk memahami. Python 3:
Python versi 2:
Jika anda ingin sesuatu yang super sederhana:
Gunakan
range()
bukanxrange()
dalam kasus Python 3.xLangsung dari (lama) Python dokumentasi (resep untuk itertools):
Versi saat ini, seperti yang disarankan oleh J. F. Sebastian:
Saya kira Guido's waktu mesin bekerja—bekerja—akan bekerja—bekerja—bekerja lagi.
Solusi ini bekerja karena
[iter(iterable)]*n
(atau setara dalam versi sebelumnya) menciptakan satu iterator, diulangn
kali dalam daftar.izip_longest
maka secara efektif melakukan round-robin dari "setiap orang" iterator; karena ini adalah sama iterator, itu maju dengan setiap panggilan tersebut, sehingga masing-masing seperti zip-roundrobin menghasilkan satu tupel darin
barang-barang.Saya tahu ini adalah jenis dari lama tapi belum ada yang disebutkan
numpy.array_split
:I'm heran tidak ada yang berpikir untuk menggunakan
iter
's dua bentuk argumen:Demo:
Ini bekerja dengan iterable dan menghasilkan output malas. Kembali tupel daripada iterator, tapi saya pikir ia memiliki keanggunan tertentu tetap. Hal ini juga doesn't pad; jika anda ingin padding, variasi sederhana di atas akan cukup:
Demo:
Seperti
izip_longest
berbasis solusi di atas always bantalan. Sejauh yang saya tahu, ada's tidak ada satu atau dua baris itertools resep untuk fungsi yang optionally bantalan. Dengan menggabungkan dua pendekatan di atas, yang satu ini datang cukup dekat:Demo:
Saya percaya ini adalah yang terpendek chunker diusulkan yang menawarkan opsional padding.
Sebagai Tomasz Gandor observed, dua padding chunkers akan berhenti secara tiba-tiba jika mereka menemukan urutan panjang dari nilai-nilai pad. Berikut ini's final variasi yang bekerja di sekitar masalah itu dengan cara yang wajar:
Demo:
Berikut ini adalah generator yang bekerja pada sewenang-wenang iterables:
Contoh:
Sederhana namun elegan
atau jika anda lebih suka:
Saya melihat yang paling mengagumkan Python-ish jawaban di duplikat dari pertanyaan ini:
Anda dapat membuat n-tuple untuk setiap n. Jika
a = range(1, 15)
, maka hasilnya akan menjadi:Jika daftar ini dibagi secara merata, kemudian anda dapat mengganti
zip_longest
denganzip
, jika tidak triplet(13, 14, Tidak ada)
akan hilang. Python 3 digunakan di atas. Untuk Python 2, menggunakanizip_longest
.Kritik dari jawaban yang lain di sini:
Tidak satupun dari jawaban-jawaban ini merata ukuran potongan, mereka semua meninggalkan kerdil chunk di akhir, sehingga mereka're tidak benar-benar seimbang. Jika anda menggunakan fungsi ini untuk mendistribusikan pekerjaan, anda've built-in prospek dari satu kemungkinan finishing yang baik di hadapan orang lain, sehingga akan duduk-duduk melakukan apa-apa sementara yang lain terus bekerja keras.
Misalnya, saat ini atas jawabannya berakhir dengan:
Aku hanya benci yang kerdil di akhir!
Yang lain, seperti
daftar(kerapu(3, xrange(7)))
, danchunk(xrange(7), 3)
kembali:[(0, 1, 2), (3, 4, 5), (6, Tidak ada, Tidak ada)]
.None
's hanya padding, dan agak janggal menurut saya. Mereka yang TIDAK merata chunking iterables.Mengapa bisa't kita membagi ini lebih baik?
Solusi saya(s)
Berikut ini's solusi seimbang, diadaptasi dari fungsi I've yang digunakan dalam produksi (Catatan di Python 3 untuk menggantikan
xrange
denganrange
):Dan saya membuat sebuah generator yang melakukan hal yang sama jika anda memasukkannya ke daftar:
Dan akhirnya, karena saya melihat bahwa semua fungsi di atas kembali unsur-unsur dalam yang bersebelahan order (seperti yang diberikan):
Output
Untuk menguji mereka:
Yang mencetak:
Perhatikan bahwa bersebelahan generator memberikan potongan sama panjang pola seperti dua lainnya, tapi item semua dalam rangka, dan mereka yang secara merata dibagi sebagai salah satu mungkin membagi daftar elemen diskrit.
Jika anda tahu daftar ukuran:
Jika anda don't (iterator):
Dalam kedua kasus, hal ini dapat diulang dalam lebih indah jika anda dapat yakin bahwa urutan selalu mengandung seluruh jumlah potongan dari ukuran tertentu (yaitu tidak ada yang tidak lengkap terakhir chunk).
Jika anda memiliki sepotong ukuran 3 misalnya, anda bisa melakukan:
sumber: http://code.activestate.com/recipes/303060-group-a-list-into-sequential-n-tuples/
Aku akan menggunakan ini ketika saya chunk size adalah jumlah tetap saya bisa mengetik, misalnya '3', dan tidak akan pernah berubah.
The toolz perpustakaan memiliki
partisi
fungsi untuk ini:Aku suka Python doc's versi diusulkan oleh tzot dan J. F. Sebastian banyak, tapi ini memiliki dua kelemahan:
I'm menggunakan yang satu ini banyak di kode saya:
UPDATE: malas potongan versi:
kode:
hasilnya:
Saya penasaran tentang kinerja pendekatan yang berbeda dan di sini adalah:
Diuji pada Python 3.5.1
Hasil:
Pada titik ini, saya pikir kita perlu rekursif generator, hanya dalam kasus...
Di python versi 2:
Di python 3:
Juga, dalam kasus invasi Alien besar, a dihiasi rekursif generator mungkin menjadi berguna:
Anda juga dapat menggunakan
get_chunks
fungsiutilspie
perpustakaan sebagai:Anda dapat menginstal
utilspie
melalui pip:Disclaimer: saya pencipta utilspie perpustakaan.
Di mana AA adalah array, SS adalah ukuran potongan. Misalnya:
heh, satu line versi