Clojure'da liste türleri arasında dönüştürme yapmanın kolay bir yolu var mı?


93

Bir vektör istediğimde kendimi genellikle tembel bir liste kullanırken buluyorum ve bunun tersi de geçerli. Ayrıca, gerçekten bir dizi harita istediğimde bazen bir harita vektörüm olur. Bu türler arasında dönüşüm yapmama yardımcı olacak herhangi bir yardımcı işlev var mı?

Yanıtlar:


148

Unutmayalım ki, güvenilir eski , mümkün olan intoher şeyi seq(liste, vektör, harita, küme, sıralı harita) ve doldurmak istediğiniz boş bir kabı alıp koymanıza izin verir into.

(into [] '(1 2 3 4)) ==> [1 2 3 4]         "have a lazy list and want a vector"
(into #{} [1 2 3 4]) ==> #{1 2 3 4}        "have a vector and want a set"
(into {} #{[1 2] [3 4]}) ==> {3 4, 1 2}    "have a set of vectors want a map"
(into #{} [{1 2} {3 4}]) ==> #{{1 2} {3 4}} "have a vector of maps want a set of maps"

intoetrafında sarıcı conjtoplama türüne göre bir koleksiyonu halinde uygun bir şekilde, yeni girdileri sokulması için temel soyutlamasıdır. Bu akışı bu kadar güzel kılan ilke, Clojure'un , bu durumda koleksiyonun intoüstüne ve conjüzerine , birleştirilebilir soyutlamalar üzerine inşa edilmesidir seq.

Yukarıdaki örnekler, alıcı çalışma zamanında aktarılıyor olsaydı yine de iyi bir şekilde oluşturacaktır: çünkü temeldeki soyutlamalar ( seqve conj) tüm koleksiyonlar için (ve Java'nın koleksiyonlarının çoğu için de) uygulanmaktadır, bu nedenle yüksek soyutlamaların endişelenmesine gerek yoktur verilerle ilgili çok sayıda özel durum.


3
+1 for into ... aynı zamanda boş olmayan orijinal kaplarla da çalıştığını belirtmeye değer (yani bir koleksiyona eklemek istediğinizde)
mikera

11
Ayrıca şunu da belirtmek gerekir ki , intokullanımlar conj, yapmanın (into '() some-seq)bir sıranın tersi olan bir liste vereceğini , çünkü conjlistelerde eksileri olduğunu belirtmek gerekir.
Chuck

intoDiğer dönüştürme araçlarının çoğundan daha iyi performans özellikleri için geçişleri (çoğu sıra türü için) kullandığını belirtmek gerekir .
Jarred Humphrey

Ve şimdi bu cevap yazılmıştır zaman (geçici ya yapsam bilmiyorum) de olmasaydı dönüştürücüler ile çalışır (Bu cevap anaokulunda kayıt eski yeterlidir)
Arthur Ulfeldt

33

vec, setVe genellikle intobaşka bir koleksiyon türüne kolayca "convert" için arkadaşlar.

Bir harita vektörünü bir harita haritasına nasıl dönüştürmek istersiniz? Bir anahtara ihtiyacınız var, örnek girdi / beklenen çıktı ile kullanım sağlayabilir misiniz?


Üzgünüm, bir dizi haritayı kastetmiştim .. Şu anda soruyu değiştirdim
appshare.co

22

Vektörler için vecfonksiyon var

user=> (vec '(1 2 3))
[1 2 3]

Tembel diziler için lazy-seqfonksiyon var

user=> (lazy-seq [1 2 3])
(1 2 3)

Setlere dönüştürmek için setfonksiyon var

user=> (set [{:a :b, :c :d} {:a :b} {:a :b}])
#{{:a :b} {:a :b, :c :d}}

4
Tembel olmayan bir çağrıya sahip olduğunuzda lazy-seq, seqsadece işe yaramaz bir yönlendirme eklemek yerine . Gerçekten boş bir koleksiyondan önce bile sıfır olmayan bir şeyi iade etmek istiyorsanız, orada sequence. lazy-seqbir şekilde düşük seviyeli bir yapıdır.
cgrand

14

Listeden haritaya dönüştürmek için (bütünlük adına) bir cevap daha - buradan :

(apply hash-map '(1 2 3 4))
;=>{1 2, 3 4}

9

Bir vektörü bir listeye dönüştürmek için, şu şekilde de kullanabilirsiniz for:

=> (for [i [1 2 3 4]] i)
(1 2 3 4)

Verileri değiştirmek istemediğinizde, sadece seqvektörde kullanın :

=> (seq [1 2 3])
(1 2 3)

forSenin yerine sadece yapabilirsin(map identity [1 2 3 4])
siltalau

7

Bir vektörü listeye dönüştürmeye gerek yoktur . Clojure, bir vektörü, bir dizi gerekli olduğunda, bir listeyi - bir dizi olarak - işleyeceği gibi ele alır. Örneğin,

user=> (cons 0 [1 2 3])
(0 1 2 3)

Vektörün bir dizi olarak değerlendirildiğinden emin olmanız gerekiyorsa, onu sarın seq:

user=> (conj [1 2 3] 0) ; treated as a vector
[1 2 3 0]

user=> (conj (seq [1 2 3]) 0) ; treated as a sequence
(0 1 2 3)

Bir harita vektörünüz varsa ve bir dizi harita istiyorsanız, vektörün haritaları tutması önemli değildir. Vektörü her zamanki gibi bir kümeye dönüştürürsünüz:

user=> (set [{:a 1, :b 2} {"three" 3, "four" 4}])
#{{:a 1, :b 2} {"four" 4, "three" 3}}
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.