2013-02-23 11 views
7

chciałbym filtrować zestaw, coś jak:Filtr zestaw w Clojure clojure.set/wybierz vs. clojure.core/filtr

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

Jeśli używam clojure.core/filter dostaję nast który nie jest set:

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

Więc najlepszym przyszedłem ze jest:

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

Ale nie podoba, to nie wygląda optymalna iść z zestawu Li st z powrotem do zestawu. Jaki byłby na to sposób Clojurian?

UPDATE

Zrobiłem następujące porównać @ A.Webb i @Beyamor podejść. Co ciekawe, oba mają prawie identyczną wydajność, ale clojure.set/select jest nieco lepszy.

(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 ! 
+2

Warto zauważyć, że wydajność 'clojure.set/select' powinien być mniej więcej taki sam jak' (zestaw (filtr ...)) '. Spróbuj ustawić czas dla dużego zestawu. Należy pamiętać, że (1) 'filter' w rzeczywistości nie tworzy całej listy, ponieważ jest leniwy i że (2) Clojure opiera się na niezmiennych strukturach danych, więc musisz zacząć puszczać naturalną niechęć do tworzenia nowych struktur. –

+0

@ A. Interesujące, zobacz moją aktualizację w pytaniu. – Blacksad

Odpowiedz

9

clojure.set to poręczne API dla wspólnego zbioru operacji.

W tym przypadku clojure.set/select jest filtrem specyficznym dla zestawu. Działa poprzez dysocjację elementów, które nie spełniają predykatu z podanego zestawu.

(require 'clojure.set) 

(clojure.set/select even? #{1 2 3 4 5}) 
; => #{2 4} 
+0

Nie wiem, jak to przegapiłem w dokumencie clojure.set. Dzięki ! – Blacksad