我正在尝试从输入map
创建一种还原索引。我得到的输入地图是:
{"id-1" {"values" ["a" "b" "c"]}, "id-2" {"values" ["a" "b" "c"]}}
然后我希望将其他地图作为结果:
{"a" ["id-1" "id-2"], "b" ["id-1" "id-2"], "c" ["id-1" "id-2"]}
然而,我认为我的思绪确实发疯了,而且我认为自己已经把自己画成了角落而没有开箱即用。这是我到目前为止所得到的,看起来很糟糕:
(->> {"id-1" {"values" ["a" "b" "c"]} "id-2" {"values" ["a" "b" "c"]}}
(map #(->> (get (second %) "values")
(map (fn [x y] (hash-map y x)) (into [] (repeat (count (get (second %) "values")) (first %))))
(apply merge-with concat)))
(apply merge-with concat))
基本上,我使用第一个map
用于"迭代"超过我的所有输入值。然后我使用第二张地图创建一系列单独的地图,如下所示:
({"a" "id-2"} {"b" "id-2"} {"c" "id-2"} {"a" "id-1"} {"b" "id-1"} {"c" "id-1"})
要访问该地图,我使用into [] (repeat ..)
创建一个中间数组,以便将值与数组一起提供给地图。
然后我将它们合并在一起以获得我的期望值。
这里有两个问题:
目前的最终结果还不完善,因为我得到了这个:
{"" (\ i \ d - \ 1 \ i \ d - \ 2)," b" (\ i \ d - \ 1 \ i \ d - \ 2)," c" (\ i \ d - \ 1 \ i \ d - \ 2)}
答案 0 :(得分:8)
(apply merge-with into (for [[k {vs "values"}] input, v vs] {v [k]}))
更明确的
(apply merge-with into
(for [[k m] input
v (get m "values")]
{v [k]}))
答案 1 :(得分:2)
鉴于此输入:
(def input {"id-1" {"values" ["a" "b" "c"]}, "id-2" {"values" ["a" "b" "c"]}})
更容易做到:
(defn extract [key values]
(for [v (get values "values")] {v [key]}))
(->> input
(mapcat (partial apply extract))
(apply merge-with concat))
或者,没有附加功能:
(->> (for [[k vs] input]
(for [v (get vs "values")] {v [k]}))
(flatten)
(apply merge-with concat))
以你想要的方式运作。
诀窍是将key
包装在extract
函数的向量中,这样merge-with concat
可以在不连接字符串的情况下工作。