您好:我想为地图中的所有值映射“平均值”。说我有一张地图清单:
[{"age" 2 "height" 1 "weight" 10},
{"age" 4 "height" 4 "weight" 20},
{"age" 7 "height" 11 "weight" 40}]
我想要的输出是
{"age 5 "height" 5 ....}
///下面是我大脑的乱音,也就是我想象这在Clojure中工作的方式......不要太认真了
转置列表:
{"age" [2 4 7] "height" [1 4 11] }
然后我可以简单地做一些事情(再次,在这里组成一个名为freduce的函数)
(freduce average (vals (map key-join list)))
获取
{"age" 5 "weight" 10 "height" 7}
答案 0 :(得分:6)
创建矢量地图:
(reduce (fn [m [k v]] (assoc m k (conj (get m k []) v))) {} (apply concat list-of-maps))
创建平均值图:
(reduce (fn [m [k v]] (assoc m k (/ (reduce + v) (count v)))) {} map-of-vectors)
答案 1 :(得分:4)
这是我的一些实际代码:
(let [maps [{"age" 2 "height" 1 "weight" 10},
{"age" 4 "height" 4 "weight" 20},
{"age" 7 "height" 11 "weight" 40}]]
(->> (apply merge-with #(conj %1 %2)
(zipmap (apply clojure.set/union (map keys maps))
(repeat [])) ; set the accumulator
maps)
(map (fn [[k v]] [k (/ (reduce + v) (count v))]))
(into {})))
答案 2 :(得分:4)
这是一个相当冗长的解决方案。希望有人可以提出更好的建议:
(let [maps [{"age" 2 "height" 1 "weight" 10},
{"age" 4 "height" 4 "weight" 20},
{"age" 7 "height" 11 "weight" 40}]
ks (keys (first maps))
series-size (count maps)
avgs (for [k ks]
(/ (reduce +
(for [m maps]
(get m k)))
series-size))]
(zipmap ks avgs))
答案 3 :(得分:2)
(defn key-join [map-list]
(let [keys (keys (first map-list))]
(into {} (for [k keys] [k (map #(% k) map-list)]))))
(defn mapf [f map]
(into {} (for [[k v] map ] [k (f v)])))
(defn average [col]
(let [n (count col)
sum (apply + col)]
(/ sum n)))
<强>样本强>
user=> (def data-list [{"age" 2 "height" 1 "weight" 10},
{"age" 4 "height" 4 "weight" 20},
{"age" 7 "height" 11 "weight" 40}])
#'user/data-list
user=> (key-join data-list)
{"age" (2 4 7), "height" (1 4 11), "weight" (10 20 40)}
user=> (mapf average (key-join data-list))
{"age" 13/3, "height" 16/3, "weight" 70/3}
答案 4 :(得分:1)
这是另一个使用merge-with而没有zipmap的版本。
(let [data [{:a 1 :b 2} {:a 2 :b 4} {:a 4 :b 8}]
num-vals (count data)]
(->> data (apply merge-with +)
(reduce (fn [m [k v]] (assoc m k (/ v num-vals))) {})))
答案 5 :(得分:1)
这是我的单线解决方案:
(def d [{"age" 2 "height" 1 "weight" 10},
{"age" 4 "height" 4 "weight" 20},
{"age" 7 "height" 11 "weight" 40}])
(into {} (map (fn [[k v] [k (/ v (count d))]]) (apply merge-with + d)))
=> {"height" 16/3, "weight" 70/3, "age" 13/3}
逻辑如下: