在clojure
中,我有一张地图,其中包含每天和每个水果,以及吃过的水果数量。我想“反转地图的层次结构”并返回相同的数据,但水果位于层次结构的顶部。
我将通过一个例子来解释:
(map-reverse-hierarchy {:monday {:banana 2 :apple 3}
:tuesday {:banana 5 :orange 2}})
; => {:orange {:tuesday 2},
; :banana {:tuesday 5, :monday 2},
; :apple {:monday 3}}
答案 0 :(得分:7)
你可以使用列表理解和一些解构,比如
user=> (->> (for [[day consum] data
#_=> [fruit amount] consum]
#_=> {fruit {day amount}})
#_=> (apply merge-with conj))
{:orange {:tuesday 2}, :banana {:tuesday 5, :monday 2}, :apple {:monday 3}}
user=>
或使用函数+ mapcat
代替:
(defn flip [[day consum]]
(map (fn [[fruit amount]] {fruit {day amount}}) consum))
(apply merge-with conj (mapcat flip data))
答案 1 :(得分:4)
我的解决方案首先转换嵌套地图的各个部分,然后将它们全部合并。
这些作品从{k1 {k2 v}}
转换为{k2 {k1 v}}
,然后由apply merge-with conj
合并
(defn map-reverse-hierarchy [mm]
(apply merge-with conj
(for [[k1 m] mm [k2 v] m] {k2 {k1 v}})))
答案 2 :(得分:1)
也许:
(defn map-reverse-hierarchy [m]
(let [foo (fn [a lst]
(map #(do [(first %) {a (second %)}]) lst))
bbb (map (fn [[a b]] (into {} (foo a b))) m)]
(if (seq bbb)
(apply merge-with merge bbb)
{})))
(map-reverse-hierarchy {:monday {:banana 2 :apple 3}
:tuesday {:banana 5 :orange 2}})
;{:banana {:monday 2, :tuesday 5}, :apple {:monday 3}, :orange {:tuesday 2}}
答案 3 :(得分:1)
我认为您需要一些自定义功能。使用clojure.set/map-invert
[1]交换hash-map中的键和值
[1] http://clojure.github.io/clojure/clojure.set-api.html#clojure.set/map-invert
蛮力解决方案:
(defn x []
(let [i {:monday {:banana 2 :apple 3}
:tuesday {:banana 5 :orange 2}}]
(reduce-kv (fn [h day fruits]
(reduce-kv (fn [h fruit n]
(update-in h [fruit day] #(+ (or % 0) n))) h fruits)) {} i)))
user> (pprint (x))
{:orange {:tuesday 2},
:banana {:tuesday 5, :monday 2},
:apple {:monday 3}}