Di Clojure, saya ingin menggabungkan dua daftar untuk memberikan daftar pasangan,
> (zip '(1 2 3) '(4 5 6))
((1 4) (2 5) (3 6))
Di Haskell atau Ruby fungsinya disebut zip . Menerapkannya tidak sulit, tetapi saya ingin memastikan saya tidak kehilangan fungsi di Core atau Contrib.
Ada ruang nama zip di Core, tetapi digambarkan sebagai menyediakan akses ke teknik fungsional Zipper, yang tampaknya tidak seperti apa yang saya cari.
Apakah ada fungsi yang setara untuk menggabungkan 2 daftar atau lebih, dengan cara ini, di Core?
Jika tidak ada, apakah itu karena ada pendekatan idiomatik yang membuat fungsi tidak dibutuhkan?
zip
fungsi di perpustakaan Tupelo: cloojure.github.io/doc/tupelo/tupelo.core.html#var-zipJawaban:
melakukan apa yang Anda inginkan:
Haskell membutuhkan kumpulan fungsi
zipWith
(zipWith3
,,zipWith4
...), karena semuanya harus dari tipe tertentu ; khususnya, jumlah daftar input yang mereka terima perlu diperbaiki. (Thezip
,zip2
,zip3
, ... keluarga dapat dianggap sebagai spesialisasi darizipWith
keluarga untuk kasus penggunaan umum dari tupling).Sebaliknya, Clojure dan Lisps lainnya memiliki dukungan yang baik untuk fungsi variabel arity;
map
adalah salah satunya dan dapat digunakan untuk "tupling" dengan cara yang mirip dengan HaskellCara idiomatis untuk membangun "tuple" di Clojure adalah dengan membuat vektor pendek, seperti yang ditampilkan di atas.
(Hanya untuk kelengkapan, perhatikan bahwa Haskell dengan beberapa ekstensi dasar memang memungkinkan fungsi variabel arity; menggunakan mereka membutuhkan pemahaman yang baik tentang bahasa, dan vanilla Haskell 98 mungkin tidak mendukung mereka sama sekali, sehingga fungsi arity tetap lebih disukai untuk perpustakaan standar.)
sumber
zip
ketika koleksi tidak sama panjangnya. Ruby akan terus memproses dan memasoknil
untuk koleksi yang lebih pendek, sedangkan Clojure akan berhenti memproses setelah salah satu koleksi habis.zip
berperilaku seperti Clojuremap
dalam hal ini.atau lebih umum
sumber
sumber
untuk memberikan apa yang Anda inginkan, pemetaan
list
di kedua daftar akan memberi Anda daftar daftar seperti pada contoh Anda. Saya pikir banyak Clojurians cenderung menggunakan vektor untuk ini meskipun itu akan bekerja dengan apa pun. dan input tidak perlu tipe yang sama. map membuat seqs dari mereka dan kemudian memetakan seqs sehingga input seq'able apa pun akan berfungsi dengan baik.sumber
Cara bawaannya hanyalah fungsi 'interleave':
sumber
(partition 2 (interleave [1 2 3 4][5 6 7 8]))
Ada fungsi yang disebut zipmap, yang mungkin memiliki efek yang sama, (zipmap
(1 2 3)
(4 5 6)) Ouput sama seperti aliran: {3 6, 2 5, 1 4}sumber
# (terapkan daftar peta%) mentransformasikan matriks seperti fungsi Python zip *. Sebagai definisi makro:
user => (defmacro py-zip [lst] `(terapkan daftar peta ~ lst))
# 'pengguna / py-zip
user => (py-zip '((1 2 3 4) (9 9 9 9) (5 6 7 8)))
((1 9 5) (2 9 6) (3 9 7) (4 9 8))
user => (py-zip '((1 9 5) (2 9 6) (3 9 7) (4 9 8)))
((1 2 3 4) (9 9 9 9) (5 6 7 8))
sumber