Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Filter a set in Clojure clojure.set/select vs. clojure.core/filter

Tags:

clojure

I would like to filter a set, something like:

(filter-set even? #{1 2 3 4 5})
; => #{2 4}

If I use clojure.core/filter I get a seq which is not a set:

(filter even? #{1 2 3 4 5})
; => (2 4)

So the best I came with is:

(set (filter even? #{1 2 3 4 5}))

But I don't like it, doesn't look optimal to go from set to list back to set. What would be the Clojurian way for this ?

UPDATE

I did the following to compare @A.Webb and @Beyamor approaches. Interestingly, both have almost identical performance, but clojure.set/select is slightly better.

(defn set-bench []
  (let [big-set (set (take 1000000 (iterate (fn [x] (int (rand 1000000000))) 1)))]
    (time (set (filter even? big-set))) ; "Elapsed time: 422.989 msecs"
    (time (clojure.set/select even? big-set))) ; "Elapsed time: 345.287 msecs"
    nil) ; don't break my REPL !
like image 610
Blacksad Avatar asked Feb 23 '13 16:02

Blacksad


1 Answers

clojure.set is a handy API for common set operations.

In this case, clojure.set/select is a set-specific filter. It works by dissociating elements which don't meet the predicate from the given set.

(require 'clojure.set)

(clojure.set/select even? #{1 2 3 4 5})
; => #{2 4} 
like image 119
Beyamor Avatar answered Sep 20 '22 17:09

Beyamor