Erlang dan Ruby keduanya dilengkapi dengan fungsi untuk meratakan array. Sepertinya alat yang sederhana dan bermanfaat untuk ditambahkan ke bahasa. Orang bisa melakukan ini:
>>> mess = [[1, [2]], 3, [[[4, 5]], 6]]
>>> mess.flatten()
[1, 2, 3, 4, 5, 6]
Atau bahkan:
>>> import itertools
>>> mess = [[1, [2]], 3, [[[4, 5]], 6]]
>>> list(itertools.flatten(mess))
[1, 2, 3, 4, 5, 6]
Sebaliknya, dalam Python, kita harus melalui kesulitan menulis fungsi untuk meratakan array dari awal. Ini tampak konyol bagi saya, meratakan array adalah hal yang biasa dilakukan. Ini seperti harus menulis fungsi khusus untuk menggabungkan dua array.
Saya telah mencari Google tanpa hasil, jadi saya bertanya di sini; adakah alasan khusus mengapa bahasa dewasa seperti Python 3, yang dilengkapi dengan ratusan ribu baterai, tidak menyediakan metode sederhana untuk meratakan susunan? Apakah gagasan untuk memasukkan fungsi semacam itu telah dibahas dan ditolak di beberapa titik?
sumber
extend
tetapi rata akan jauh lebih elegan. Namun, saya luka jika pola ini cukup umum untuk membenarkan memiliki rata di perpustakaan standar.Jawaban:
Proposal untuk
flatten
fungsi yang akan ditambahkan ke pustaka standar muncul dari waktu ke waktu pada milis python-dev dan python-ideas . Pengembang Python biasanya merespons dengan hal-hal berikut:Ratakan satu tingkat (mengubah iterable dari iterables menjadi iterable tunggal) adalah ekspresi satu-baris yang sepele
(x for y in z for x in y)
dan dalam hal apa pun sudah ada di perpustakaan standar di bawah namanyaitertools.chain.from_iterable
.Apa kasus penggunaan untuk perataan multi-level untuk keperluan umum? Apakah ini benar-benar cukup menarik untuk ditambahkan fungsi ke perpustakaan standar?
Bagaimana alat multi-level untuk keperluan umum akan memutuskan kapan harus merata dan kapan pergi sendiri? Anda mungkin berpikir bahwa aturan seperti "meratakan apa pun yang mendukung antarmuka iterable" akan berfungsi, tetapi itu akan menyebabkan loop tak terbatas untuk
flatten('a')
.Lihat misalnya Raymond Hettinger :
sumber
flatten
dapat didefinisikan sebagailambda z: [x for y in z for x in y]
.flatten
metode. Implementasi metode ini harus memanggilflatten
subkomponennya secara rekursif , jika objeknya adalah komposit. Sayangnya, AFAIK tidak setiap nilai adalah objek dengan Python. Di Ruby itu seharusnya bekerja.Itu memang datang dengan metode seperti itu tetapi tidak menyebutnya rata. Ini disebut " rantai ". Ini mengembalikan iterator yang kemudian Anda harus menggunakan fungsi daftar () untuk mengubahnya kembali menjadi daftar. Jika Anda tidak ingin menggunakan *, Anda dapat menggunakan versi "from_iterator" kedua. Ia bekerja sama di Python 3. Ini akan gagal jika input daftar bukan daftar daftar.
Ada suatu waktu metode rata dalam modul compiler.ast tapi ini tidak digunakan lagi di 2.6 dan kemudian dihapus di 3.0. Rekursi kedalaman sewenang-wenang, yang diperlukan untuk daftar yang tersarang secara arbitrer tidak berfungsi dengan baik dengan kedalaman rekursi maksimum konservatif Python. Alasan penghapusan kompiler sebagian besar karena itu menjadi berantakan . Kompiler berubah menjadi ast tetapi pipih tertinggal.
Kedalaman sewenang-wenang dapat dicapai dengan susunan numpy dan pustaka yang rata.
sumber
chain.from_iterator
fungsi, seperti yang Anda katakan, hanya dapat digunakan untuk meratakan daftar dua dimensi. Sebuah sebenarnya fungsi meratakan, yang menerima setiap jumlah daftar bersarang dan kembali daftar satu dimensi, masih akan besar-besaran berguna dalam banyak kasus (setidaknya menurut saya)... mungkin karena tidak sulit untuk menulisnya sendiri
... dan kemudian ratakan semua yang Anda inginkan :)
sumber