Clojureでは、リストのタイプ間で変換する簡単な方法はありますか?


92

私はベクターが必要なときに怠惰なリストを使用していることがよくあり、逆もまた同様です。また、マップのセットが本当に必要なときに、マップのベクターを持っていることがあります。これらのタイプ間で変換するのに役立つヘルパー関数はありますか?

回答:


144

trusty old intoでは、何でもseqできるもの(リスト、ベクター、マップ、セット、ソートマップ)と、必要な空のコンテナーを取得して配置できることを忘れないでください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"

intoは、ラッパーですconj。これは、コレクションのタイプに基づいて新しいエントリをコレクションに適切に挿入するための基本的な抽象化です。このフローを非常に美しくする原則は、Clojureが構成可能な抽象化に基づいて構築されていることです。この場合intoconj、コレクションの上に追加されseqます。

上記の例は、実行時に受信者が渡された場合でも適切に構成されます。基礎となる抽象(seqおよびconj)がすべてのコレクション(およびJavaのコレクションの多くも)に実装されているため、上位の抽象は心配する必要はありません。多くの特別なデータ関連のコーナーケースについて。


3
+1 for into ...は、空ではない元のコンテナでも機能する(つまり、コレクションに追加したい場合)
mikera

11
また、intouses conj、doing (into '() some-seq)はsome-seqの逆のリストを生成するため、conjコンストレイントを使用するため、注目に値します。
チャック

into他のほとんどの変換手段よりも優れたパフォーマンス特性を得るために、トランジェント(ほとんどのseqタイプ)を利用していることは注目に値します。
ジャレッドハンフリー

そして現在、この回答が書かれたときに存在しなかったトランスデューサーで動作します(トランジェントも発生したかどうかはわかりません)(この回答は幼稚園に入学するのに十分古い)
Arthur Ulfeldt

33

vecsetそして一般的にintoはあなたの友達で、別のコレクション型に簡単に「変換」することができます。

マップのベクトルをマップのマップにどのように変換しますか?キーが必要ですが、サンプル入力/期待される出力を使用できますか?


申し訳ありませんが、私は一連のマップを意味しました。今、質問を修正しました
appshare.co

22

ベクトルにはvec関数があります

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

レイジーシーケンスにはlazy-seq関数があります

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

セットに変換するためのset関数があります

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

4
単に無意味な間接参照を追加するlazy-seqseqではなく、非遅延呼び出しがある場合。本当にあなたが前の空のコレクションでさえnil以外のものを返したいなら、がありますsequencelazy-seqやや低レベルの構成です。
cgrand

14

(完全にするために)リストからマップに変換するためのもう1つの答え- ここから:

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

9

ベクトルをリストに変換するにはfor、次のようにを使用することもできます。

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

データを操作したくない場合seqは、ベクターで使用します。

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

forあなたの代わりにただ行うことができます(map identity [1 2 3 4])
シルタラウ

7

ベクトルをリストに変換する必要はありません。Clojureは、シーケンスが必要な場合に、リストをシーケンスとして扱うようにベクトルを扱います。例えば、

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

ベクトルがシーケンスとして扱われていることを確認する必要がある場合は、次のようにラップし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)

マップのベクトルがあり、マップのセットが必要な場合、ベクトルがマップを保持しているかどうかは関係ありません。いつものようにベクトルをセットに変換するだけです:

user=> (set [{:a 1, :b 2} {"three" 3, "four" 4}])
#{{:a 1, :b 2} {"four" 4, "three" 3}}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.