2017-12-28 5 views
0

Gegeben eine Datenstruktur, ich möchte es neu strukturieren, um von einem der verschachtelten Werte gruppiert werden. Diese Werte sind Vektoren, und wenn ich auf mehr als einen Wert stoße, bleibe ich stecken.Clojure/Clojurescript: group-by eine Karte auf mehrere Werte

einen Vektor von Karten wie folgt gegeben:

(def tools 
[{:name "A", 
    :config 
    {:accepts ["id"], 
    :classes ["X"]}} 
    {:name "B", 
    :config 
    {:accepts ["id"], 
    :classes ["X", "Y"] 
    }}]) 

Ich kann fast bekommen, was ich will - die von „Klassen“ sortierten Werte als Schlüssel, wiederholt mit Werten wenn nötig - durch group-by läuft :

(group-by #(get-in % [:config :classes]) tools) 

Aber es dauert den ganzen Vektor in :classes als Schlüssel.

{["X"] [{:name "A", 
      :config {:accepts ["id"], 
        :classes ["X"]}}], 
    ["X" "Y"] [{:name "B", 
       :config {:accepts ["id"], 
         :classes ["X" "Y"]}}]} 

Was ich wirklich will pro Klasse die Werte einmal zu kopieren, wie folgt aussehen:

{"X" [{:name "A" 
     :config {:accepts ["id"] 
       :classes ["X"]}} 
     {:name "B" 
     :config {:accepts ["id"] 
       :classes ["X" "Y"]}}] 
    "Y" [{:name "B" 
     :config {:accepts ["id"] 
       :classes ["X" "Y"]}}]} 

Ich bin nicht ganz sicher, wie dies gegeben zu handhaben, dass ich mehrere Werte in classes haben .

Arbeiten repl Demo: https://repl.it/@YoYehudi/FamiliarDisguisedXiphiasgladius

Antwort

3

Hier ist ein Weg, es zu tun, um ein verschachteltes reduce mit:

(defn aggregate-classes [m tool] 
    (->> (get-in tool [:config :classes]) 
     (reduce (fn [acc elem] 
       (update acc elem conj tool)) 
       m))) 

(reduce aggregate-classes {} tools) 
=> 
{"X" ({:name "B", :config {:accepts ["id"], :classes ["X" "Y"]}} {:name "A", :config {:accepts ["id"], :classes ["X"]}}), 
"Y" ({:name "B", :config {:accepts ["id"], :classes ["X" "Y"]}})} 
3
(apply merge-with into {} 
     (for [tool tools 
      class (get-in tool [:config :classes])] 
     {class [tool]})) 
+0

Nice! Dies ist auch _much_ schneller als die 'reduce'-Version. –