Clojure / Clojurescript:按多个值的映射分组

Clojure / Clojurescript: group-by a map on multiple values

给定一个数据结构,我想重新构造它以按其中一个嵌套值分组。这些值是向量,每当遇到多个值时,我就会卡住。

给定一个这样的地图矢量:

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

我可以 几乎 得到我想要的 - 按 "classes" 作为键排序的值,如果需要重复值 - 按 运行 group-by:

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

但是它是以:classes中的整个向量作为key。

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

我真正想要的是每个 class 复制一次值,看起来像这样:

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

考虑到我在 classes 中有多个值,我不太确定如何处理这个问题。

正在运行的 repl 演示:https://repl.it/@YoYehudi/FamiliarDisguisedXiphiasgladius

这是一种使用嵌套 reduce 的方法:

(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"]}})}
(apply merge-with into {}
       (for [tool tools
             class (get-in tool [:config :classes])]
         {class [tool]}))