如何使用 assoc-in 更新地图中的多个值? (Clojure)
How to use assoc-in to update multiple values in a map? (Clojure)
我正在尝试将 "enjoy-clojure?" 为 returns true "sanity-rating" 的每一行更新为 -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)
仅 returns 更新一个元素)。要过滤学生数据库以取出返回 true 的学生,我有
(defn unhinged?
[record]
(:enjoy-clojure? record))
(defn minus-two-students
[student-database]
(filter #(unhinged? %)
(map student-database [0 1 2 3 4])))
和returns
({: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。任何 helps/tips 将不胜感激。
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)
要更新整个数据库,您可以这样做:
(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} ...}
最简单的是这样的:
(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}}
你在你的问题中没有说你希望函数 returns 仅 (= 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})
我正在尝试将 "enjoy-clojure?" 为 returns true "sanity-rating" 的每一行更新为 -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)
仅 returns 更新一个元素)。要过滤学生数据库以取出返回 true 的学生,我有
(defn unhinged?
[record]
(:enjoy-clojure? record))
(defn minus-two-students
[student-database]
(filter #(unhinged? %)
(map student-database [0 1 2 3 4])))
和returns
({: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。任何 helps/tips 将不胜感激。
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)
要更新整个数据库,您可以这样做:
(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} ...}
最简单的是这样的:
(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}}
你在你的问题中没有说你希望函数 returns 仅 (= 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})