2012-02-01 15 views
14

Jak pogrupować kolekcję map według wielu kluczy?grupowanie według wielu kluczy w Clojure

Na przykład:

(def m1 [{:a 1 :b 2 :c 3} 
     {:a 1 :b 2 :c 4} 
     {:a 1 :b 4 :c 3} 
     {:a 1 :b 4 :c 3}]) 

(group-by-x [:a :b] m1) 

Chciałbym wrócić w tym:

[{:a 1 :b 2} [{:a 1 :b 2 :c 3}{:a 1 :b 2 :c 4}], 
{:a 1 :b 4} [{:a 1 :b 4 :c 3}{:a 1 :b 4 :c 3}]] 

Odpowiedz

18
(group-by #(select-keys % [:a :b]) m1) 

Zwraca mapę:

{{:b 2, :a 1} [{:a 1, :c 3, :b 2} {:a 1, :c 4, :b 2}], 
{:b 4, :a 1} [{:a 1, :c 3, :b 4} {:a 1, :c 3, :b 4}]} 

aby uzyskać dokładnie wartości zwracanej podałeś, zawiń go w (vec (apply concat ...)):

(vec (apply concat (group-by #(select-keys % [:a :b]) m1))) 
; => as in the question text 

Jest to równoważne, ale chyba ładniej:

(->> (group-by #(select-keys % [:a :b]) m1) 
    (apply concat) 
    vec) 
+9

Można także '(grupa-by (juxt: a: b) coll)', która daje par zamiast mapach klucze. Często będzie to bardziej przydatny format niż dziesiątki map z kluczami ': a' i': b', ale to zależy wyłącznie od twojej aplikacji. – amalloy

+0

@amalloy: Racja. To było to, co napisałem przed realizacją specyfikacji wzywa do mapy. Uzgodnione wektory są prawdopodobnie bardziej przydatne, powinienem był uwzględnić to w odpowiedzi ... Dzięki za naprawienie tego rażącego pominięcia. :-) –

Powiązane problemy