Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I merge two sequences in clojure?

What is an idiomatic way to merge (or retrieve the union of) two lists (or sequences) in Clojure?

(merge l1 l2)

doesn't seem to be the solution:

a=> (merge '(1 2 3) '(2 3 4))
((2 3 4) 1 2 3)
like image 749
user1639206 Avatar asked Sep 30 '12 03:09

user1639206


People also ask

How do I merge two maps in Clojure?

Returns a map that consists of the rest of the maps conj-ed onto the first. If a key occurs in more than one map, the mapping(s) from the latter (left-to-right) will be combined with the mapping in the result.

What is a vector in Clojure?

Advertisements. A Vector is a collection of values indexed by contiguous integers. A vector is created by using the vector method in Clojure.


3 Answers

I think andih's solution works great. Here is an alternate way because hey why not. It uses concat and distinct:

user> (distinct (concat '(1 2 3) '(2 3 4)))
=> (1 2 3 4)
like image 103
Omri Bernstein Avatar answered Oct 08 '22 14:10

Omri Bernstein


If what you want is actually distinct unsorted data (sets), you should be using Clojure's set data structure instead of vectors or lists. And as andih suggested indirectly, there is a core library for set operations: 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}

If sets are for whatever reason not what you want, then read on. Careful with concat when you have a significant amount of data in your sequences, and consider using into which is much better optimized as a vector merging algorithm. I don't know why concat is not implemented using into (or better yet-- why does concat even exist? BTW while into is significantly faster than concat, it is still way way slower than conj. Bagwell's RRB trees, compatible with both Clojure and Scala, will solve this problem, but are not yet implemented for Clojure).

To rephrase Omri's non-set solution in terms of 'into':

(distinct (into [1 2 3] [3 4 5]))
=> (1 2 3 4 5)
like image 30
rplevy Avatar answered Oct 08 '22 14:10

rplevy


One way to get the union of two lists is to use union

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

or if you want to get a list

(into '() (into #{} (clojure.set/union '(1,2,3) '(3,4,5))))
(5 4 3 2 1)
like image 42
andih Avatar answered Oct 08 '22 15:10

andih