Clojure Core veya Contrib'ta Zip işlevinin bir eşdeğeri var mı?


130

Clojure'da, çiftlerin bir listesini vermek için iki listeyi birleştirmek istiyorum,

> (zip '(1 2 3) '(4 5 6))  
((1 4) (2 5) (3 6))

Haskell veya Ruby'de işleve zip denir . Bunu uygulamak zor değil, ancak Core veya Contrib'ta eksik olmadığımdan emin olmak istedim.

Core'da bir zip ad alanı var, ancak bu, peşinde olduğum gibi görünmeyen Fermuar işlevsel tekniğine erişim sağlamak olarak tanımlanıyor .

Bu şekilde Core'da 2 veya daha fazla listeyi birleştirmek için eşdeğer bir işlev var mı?

Eğer yoksa, işlevi gereksiz kılan deyimsel bir yaklaşım var olduğu için mi?


zipTupelo kitaplığında bir işlev var : cloojure.github.io/doc/tupelo/tupelo.core.html#var-zip
Alan Thompson

Yanıtlar:


220
(map vector '(1 2 3) '(4 5 6))

ne istersen yapar:

=> ([1 4] [2 5] [3 6])

Haskell'in zipWith( zipWith3,, zipWith4...) işlevler koleksiyonuna ihtiyacı vardır , çünkü hepsinin belirli bir türde olması gerekir ; özellikle, kabul ettikleri giriş listelerinin sayısının sabitlenmesi gerekir. ( zip, zip2, zip3, ... aile bir uzmanlık olarak görülebilir zipWithtupling ortak kullanım durumu için ailesi).

Bunun tersine, Clojure ve diğer Lisp'ler, değişken arity fonksiyonları için iyi bir desteğe sahiptir; mapbunlardan biridir ve Haskell'inkine benzer bir şekilde "tupling" için kullanılabilir.

zipWith (\x y -> (x, y))

Clojure'da bir "demet" oluşturmanın deyimsel yolu, yukarıda gösterildiği gibi kısa bir vektör oluşturmaktır.

(Tamlık adına, Haskell'in bazı temel uzantılarla birlikte değişken arity işlevlerine izin verdiğini unutmayın; bunları kullanmak, dilin iyi anlaşılmasını gerektirir ve vanilya Haskell 98 muhtemelen bunları hiç desteklemiyor, bu nedenle sabit arity işlevleri tercih edilir. standart kitaplık için.)


8
Bunun zip, koleksiyonların aynı uzunlukta olmadığı durumlardan farklı davrandığına dikkat edin. Ruby nil, daha kısa koleksiyon için işlemeye ve tedarik etmeye devam edecek , oysa Clojure koleksiyonlardan biri bittiğinde işlemeyi durduracaktır.
Nate W.

@NateW. Bunu not etmek güzel, teşekkürler. Haskell'de bu açıdan zipClojure'unki gibi davranır map.
Michał Marczyk

1
Değişken arity Haskell fonksiyonları hakkında bir referans isteyebilir miyim?
Teodor

23
(partition 2 (interleave '(1 2 3) '(4 5 6))) 
=> ((1 4) (2 5) (3 6))

veya daha genel olarak

(defn zip [& colls]
  (partition (count colls) (apply interleave colls)))

(zip '( 1 2 3) '(4 5 6))           ;=> ((1 4) (2 5) (3 6))

(zip '( 1 2 3) '(4 5 6) '(2 4 8))  ;=> ((1 4 2) (2 5 4) (3 6 8))


11

size tam olarak ne istediğinizi vermek için list, iki listeyi eşleştirmek size örneğinizdeki gibi bir liste listesi verecektir. Bence pek çok Clojuryalı bunun için vektörleri kullanma eğiliminde olacak, ancak bu her şeyle işe yarayacak. ve girişlerin aynı tip olması gerekmez. map onlardan sıralar oluşturur ve ardından sıraları eşler, böylece herhangi bir sıralı giriş iyi çalışır.

(map list '(1 2 3) '(4 5 6))
(map list  [1 2 3] '(4 5 6))
(map hash-map  '(1 2 3) '(4 5 6))
(map hash-set  '(1 2 3) '(4 5 6))

1
Sanırım harita ve küme yerine hash-map ve hash-set'i kastediyorsunuz.
29'da cgrand

3

Yerleşik yol, basitçe 'serpiştirme' işlevi olacaktır:

(interleave [1 2 3 4] [5 6 7 8]) => [1 5 2 6 3 7 4 8]

6
OP'nin amacına ulaşmak için eklemelisiniz(partition 2 (interleave [1 2 3 4][5 6 7 8]))
skuro

evet - Görünüşe göre OP'nin istenen çıktılarına çok yakından bakmadım.
lsh

-1

Benzer etkiye sahip olabilecek zipmap adında bir işlev vardır (zipmap (1 2 3)(4 5 6)) Çıktı fllows gibidir: {3 6, 2 5, 1 4}


zipmap size siparişi garanti etmeyen bir harita döndürür
Ilya Shinkarenko

-2

# (harita listesini uygula%) tıpkı Python zip * işlevi gibi bir matrisi dönüştürür. Makro tanımı olarak:

user => (defmacro py-zip [lst] `(harita listesini uygula ~ lst))

# 'Kullanıcı / py-zip

kullanıcı => (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))

kullanıcı => (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))


Bu nasıl 'harita' kullanmaktan daha iyi? Ve burada bir makronun amacı nedir?
Dave Newton
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.