2012-02-01 11 views
14

Come raggruppare una raccolta di mappe con più chiavi?raggruppamento con più chiavi in ​​Clojure

Ad esempio:

(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) 

mi piacerebbe tornare in questo modo:

[{: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}]] 

risposta

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

Questo restituisce una mappa:

{{: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}]} 

per ottenere esattamente il valore di ritorno hai specificato, avvolgilo in (vec (apply concat ...)):

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

Ciò equivale, ma forse più bella:

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

È anche possibile '(gruppo-by (juxt: a: b) Coll)', che vi dà le coppie invece di mappe come i tasti. Spesso questo sarà un formato più utile che avere dozzine di mappe con le chiavi ': a' e': b', ma dipende interamente dalla tua applicazione. – amalloy

+0

@amalloy: giusto. Questo è quello che ho scritto prima di realizzare le richieste specifiche per una mappa. D'accordo sul fatto che i vettori siano probabilmente più utili, avrei dovuto includerlo nella risposta ... Grazie per aver risolto questa omissione clamorosa. :-) –