是否有一种简单的方法可以将键值列表转换为映射,同时还可以有条件地重命名键?
示例:
[{:count 4, :happened "true"} {:count 1, :happened "false"}]
转换为:
{:happened-count: 4, :didnt-happen-count: 1}
我有点接近:
user=> (def foo [{:count 4, :happened "true"} {:count 1, :happened "false"}])
user=> (into {} (map (juxt :happened :count) foo))
{"true" 4, "false" 1}
edit:这可行,但是很难看。希望有更好的东西:
(clojure.set/rename-keys (into {} (map (juxt :happened :count) foo)) {"true" :happened-count "false" :didnt-happen-count})
答案 0 :(得分:3)
我宁愿使用简单归约法
(def mapping {"true" :happened-count "false" :didnt-happen-count})
(reduce #(assoc % (-> %2 :happened mapping) (:count %2)) {} data)
;;=> {:happened-count 4, :didnt-happen-count 1}
答案 1 :(得分:2)
如果有帮助,可以使用->>
宏将转换视为管道:
(->> [{:count 4, :happened "true"} {:count 1, :happened "false"}]
(map (juxt :happened :count))
(into {})
(clojure.set/rename-keys {"true" :happened-count
"false" :didnt-happen-count}))
例如首先提取值,然后将它们分组到新地图中,然后重命名键
答案 2 :(得分:1)
有百万种方法可以解决这样的问题。我喜欢明确说明这些步骤。这是我的想法:
(ns tst.demo.core
(:use demo.core tupelo.core tupelo.test))
(dotest
(let [data [{:count 4, :happened "true"}
{:count 1, :happened "false"}
{:count 5, :happened "true"}
{:count 3, :happened "false"}]
data-split (group-by :happened data)
sum-count (fn [recs]
(reduce +
(mapv :count recs)))
result {:happened-num (sum-count (get data-split "true"))
:didnt-happen-num (sum-count (get data-split "false"))}]
(is= data-split
{"true" [{:count 4, :happened "true"}
{:count 5, :happened "true"}],
"false" [{:count 1, :happened "false"}
{:count 3, :happened "false"}]} )
(is= result {:happened-num 9, :didnt-happen-num 4})))
我为真假案例添加了多条记录,因为这似乎是一个更典型的用例。