web-dev-qa-db-ja.com

clojureで2つのシーケンスをマージするにはどうすればよいですか?

Clojureで2つのリスト(またはシーケンス)をマージ(または結合を取得)する慣用的な方法は何ですか?

(merge l1 l2)

解決策ではないようです:

a=> (merge '(1 2 3) '(2 3 4))
((2 3 4) 1 2 3)
29
user1639206

Andihのソリューションは素晴らしいと思います。これが別の方法です。 concat および distinct を使用します。

user> (distinct (concat '(1 2 3) '(2 3 4)))
=> (1 2 3 4)
28
Omri Bernstein

2つのリストの和集合を取得する1つの方法は、unionを使用することです

Clojure> (into #{} (clojure.set/union '(1,2,3) '(3,4,5)))
#{1 2 3 4 5}

またはリストを取得したい場合

(into '() (into #{} (clojure.set/union '(1,2,3) '(3,4,5))))
(5 4 3 2 1)
14
andih

必要なのが実際には個別の未ソートデータ(セット)である場合は、ベクトルまたはリストの代わりにClojureのセットデータ構造を使用する必要があります。 andihが間接的に示唆したように、集合演算のコアライブラリがあります。 http://clojure.github.com/clojure/clojure.set-api.html

(require '[clojure.set :refer [union]])

(union #{1 2 3} #{3 4 5})
=> #{1 2 3 4 5}

セットがあなたが望むものではなく、何らかの理由である場合は、読み進めてください。シーケンスに大量のデータがある場合はconcatに注意し、ベクトルマージアルゴリズムとして最適化されたintoの使用を検討してください。 intoを使用してconcatが実装されていない理由はわかりません(または、さらに優れています-concatはなぜ存在するのでしょうか?) Scalaはこの問題を解決しますが、Clojureにはまだ実装されていません。

Omriの未設定のソリューションを「into」の観点から言い換えるには:

(distinct (into [1 2 3] [3 4 5]))
=> (1 2 3 4 5)
14
rplevy

重複を気にしないのであれば、 concat を試すことができます:

(concat '(1 2 3 ) '(4 5 6 1) '(2 3)) 
;;==> (1 2 3 4 5 6 1 2 3) 
7
Kevin Zhu

1つのオプションは flatten

(def colls '((1 2 3) (2 3 4)))
(flatten colls) ;; => (1 2 3 2 3 4)
(distinct (flatten colls)) ;; => (1 2 3 4)

知っておくべきことの1つは、深くネストされたコレクションを平坦化することです。

(flatten [[1 2 [3 4 5]] [1 [2 [3 4]]]]) ;; => (1 2 3 4 5 1 2 3 4)

ただし、マップではうまく機能します。

(flatten [[{} {} {}] [{} {} {}]]) ;; => ({} {} {} {} {} {})
2
Kris