如何使用assoc-in更新地图中的多个值? (Clojure的)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何使用assoc-in更新地图中的多个值? (Clojure的)相关的知识,希望对你有一定的参考价值。
我正在尝试更新每个有“享受 - 乐趣”的行吗?将真正的“理智等级”返回到-2(即约翰尼的理智等级将更新为-2)
(def student-database
{ 0 {:enjoy-clojure? false, :name "jimmy",:sanity-rating 9}
1 { :enjoy-clojure? true, :name "johnny",:sanity-rating 2}
2 { :enjoy-clojure? true, :name "jilly",:sanity-rating 5}
3 { :enjoy-clojure? true, :name "janey",:sanity-rating 8}
4 {:enjoy-clojure? false, :name "jelly",:sanity-rating 10}})
我是Clojure的新手并且尝试过研究更新和关联,并且似乎无法真正找到更新多个元素的方法((assoc student-database [0 :sanity-rating] -2)
只返回更新一个元素)。过滤学生数据库,以取出我所拥有的返回真实的学生
(defn unhinged?
[record]
(:enjoy-clojure? record))
(defn minus-two-students
[student-database]
(filter #(unhinged? %)
(map student-database [0 1 2 3 4])))
并返回
({:enjoy-clojure? true, :name "johnny", :sanity-rating 2} {:enjoy-clojure?
true, :name "jilly", :sanity-rating 5} {:enjoy-clojure? true, :name
"janey", :sanity-rating 8})
哪个效果很好但我还需要它将所有的理智等级更新为-2。任何帮助/提示将非常感激。
答案
你没有在你的问题中说你希望函数只返回(= enjoy-clojure? true)
记录,但是根据你在其他答案中的评论,我觉得这就是你真正想要的。
也许这个?
(defn unhinged?
[record]
(:enjoy-clojure? record))
(defn minus-two-students
[student-database]
(->> student-database
vals
(filter unhinged?)
(map #(assoc % :sanity-rating -2))))
输出将是
({:enjoy-clojure? true, :name "johnny", :sanity-rating -2}
{:enjoy-clojure? true, :name "jilly", :sanity-rating -2}
{:enjoy-clojure? true, :name "janey", :sanity-rating -2})
另一答案
这是reduce-kv
版本!
(defn adjust-sanity [student]
(if (:enjoy-clojure? student)
(assoc student :sanity-rating -2)
student))
(reduce-kv (fn [m k v] (assoc m k (adjust-sanity v)))
{}
student-database)
=>
{0 {:enjoy-clojure? false, :name "jimmy", :sanity-rating 9},
1 {:enjoy-clojure? true, :name "johnny", :sanity-rating -2},
2 {:enjoy-clojure? true, :name "jilly", :sanity-rating -2},
3 {:enjoy-clojure? true, :name "janey", :sanity-rating -2},
4 {:enjoy-clojure? false, :name "jelly", :sanity-rating 10}}
或者使用辅助函数来更新所有地图值的另一个选项:
(defn update-vals [m f]
(reduce-kv (fn [m' k v] (assoc m' k (f v))) {} m))
(update-vals student-database adjust-sanity)
另一答案
最简单的是这样的:
(reduce-kv (fn [acc idx row]
(assoc acc idx
(if (:enjoy-clojure? row)
(assoc row :sanity-rating -2)
row)))
{}
student-database)
;;=> {0 {:enjoy-clojure? false, :name "jimmy", :sanity-rating 9},
;; 1 {:enjoy-clojure? true, :name "johnny", :sanity-rating -2},
;; 2 {:enjoy-clojure? true, :name "jilly", :sanity-rating -2},
;; 3 {:enjoy-clojure? true, :name "janey", :sanity-rating -2},
;; 4 {:enjoy-clojure? false, :name "jelly", :sanity-rating 10}}
你也可以这样做:
(reduce-kv (fn [res k {ec? :enjoy-clojure?}]
(if ec?
(assoc-in res [k :sanity-rating] -2)
res))
student-database
student-database)
;;=> {0 {:enjoy-clojure? false, :name "jimmy", :sanity-rating 9},
;; 1 {:enjoy-clojure? true, :name "johnny", :sanity-rating -2},
;; 2 {:enjoy-clojure? true, :name "jilly", :sanity-rating -2},
;; 3 {:enjoy-clojure? true, :name "janey", :sanity-rating -2},
;; 4 {:enjoy-clojure? false, :name "jelly", :sanity-rating 10}}
另一答案
要更新整个数据库,您可以执行以下操作:
(def student-database
{0 {:enjoy-clojure? false, :name "jimmy",:sanity-rating 9}
1 { :enjoy-clojure? true, :name "johnny",:sanity-rating 2}
2 { :enjoy-clojure? true, :name "jilly",:sanity-rating 5}
3 { :enjoy-clojure? true, :name "janey",:sanity-rating 8}
4 {:enjoy-clojure? false, :name "jelly",:sanity-rating 10}})
(defn update-db [db]
(zipmap (keys db)
(map (fn [student]
(cond-> student
(:enjoy-clojure? student)
(assoc :sanity-rating -2)))
(vals db))))
(update-db student-database) ;;=>
{0 {:enjoy-clojure? false, :name "jimmy", :sanity-rating 9},
1 {:enjoy-clojure? true, :name "johnny", :sanity-rating -2} ...}
以上是关于如何使用assoc-in更新地图中的多个值? (Clojure的)的主要内容,如果未能解决你的问题,请参考以下文章
Nextjs:如何使用具有多个值的 ContextAPI,所有这些值都需要从子组件中更新
Groovy - 如何在不更新地图的情况下使用默认值获取地图值