我可以“转置”吗? Clojure 中的映射列表转换为列表映射?

发布于 2024-12-11 19:44:02 字数 562 浏览 0 评论 0原文

你好,huys:我想为地图中的所有值绘制“平均值”。假设我有一个映射列表:

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

Hi huys : I want to map a "average" for all values in a map. say I have a list of maps :

[{"age" 2 "height" 1 "weight" 10},
{"age" 4 "height" 4 "weight" 20},
{"age" 7 "height" 11 "weight" 40}]

And my desired output is

{"age 5 "height" 5 ....}

///Below are the ramblings of my brain, i.e. the way I might imagine this working in Clojure...not to be taken too seriously

transpose the list :

  {"age" [2 4 7] "height" [1 4 11] } 

and then I could simply do something like (again, making up a function called freduce here)

  (freduce average (vals (map key-join list)))

to get

{"age" 5 "weight" 10 "height" 7}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

殤城〤 2024-12-18 19:44:02

创建向量图:

(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)

Create the map of vectors:

(reduce (fn [m [k v]]
          (assoc m k (conj (get m k []) v)))
        {}
        (apply concat list-of-maps))

Create the map of averages:

(reduce (fn [m [k v]]
          (assoc m k (/ (reduce + v) (count v))))
        {}
        map-of-vectors)
表情可笑 2024-12-18 19:44:02

看看 merge-with

这是我的一些实际代码:

(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 {})))

Take a look at merge-with

Here's my go at some actual code:

(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 {})))
浮萍、无处依 2024-12-18 19:44:02

这是一个相当详细的解决方案。希望有人能想出更好的办法:

(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))

Here's a fairly verbose solution. Hopefully someone can come up with something better:

(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))
黑凤梨 2024-12-18 19:44:02
(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}
(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)))

DEMO

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}
沧笙踏歌 2024-12-18 19:44:02

这是另一个使用 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))) {})))

Here's another version that uses merge-with without 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))) {})))
娇柔作态 2024-12-18 19:44:02

这是我的单行解决方案:

(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}

逻辑如下:

  • 在映射上使用 merge-with + 来计算每个键值的总和
  • 将所有结果值除以映射总数以获得平均值
  • 将结果放回到哈希映射中(进入 {} ...)

Here's my one-liner solution:

(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}

Logics as follows:

  • Use merge-with + on the maps to calculate a sum for each key value
  • Divide all the resulting values by the total number of maps to get an average
  • Put the results back in a hashmap with (into {} ...)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文