如何更新clojure的第一级
在中使用update时,我们需要提供元素的完整路径。但如果我想更新第二级键为MaxInclude的所有元素,该怎么办 e、 g输入为如何更新clojure的第一级,clojure,Clojure,在中使用update时,我们需要提供元素的完整路径。但如果我想更新第二级键为MaxInclude的所有元素,该怎么办 e、 g输入为 (def a {:store {:type "varchar"}, :amount {:nullable true, :length nil, :type "float", :MaxInclude "100.02"}, :unit {:type "int"}, :unit-uniform {:type "int" :MaxInclude "100"} })
(def a {:store {:type "varchar"},
:amount {:nullable true, :length nil, :type "float", :MaxInclude "100.02"},
:unit {:type "int"},
:unit-uniform {:type "int" :MaxInclude "100"}
})
所需的输出是(根据IE类型将MaxInclude从字符串转换为float/int):
在这里,我映射键值对,并将每个键值对分解为k和v。然后,如果值包含:MaxInclude
,则我在该值上使用updatein
。最后,我将列表中的成对数据倒入一个哈希映射中
注:
- 如果主映射的任何值不是索引集合,则
包含?
时会出现错误
- 我使用
readstring
作为一种方便的方法,将字符串转换为数字,就像Clojure阅读器编译数字文本字符串时所做的那样。这种方法可能有缺点
我在想,如果在
中有一个类似于update的函数,它可以匹配键谓词函数,而不是精确的键值,那就太好了。这就是我想到的:
(defn update-all
"Like update-in except the second parameter is a vector of predicate
functions taking keys as arguments. Updates all values contained at a
matching path. Looks for keys in maps only."
[m [key-pred & key-preds] update-fn]
(if (map? m)
(let [matching-keys (filter key-pred (keys m))
f (fn [acc k]
(update-in acc [k] (if key-preds
#(update-all %
key-preds
update-fn)
update-fn)))]
(reduce f m matching-keys))
m))
有了这些,您所需要做的就是:
(update-all a [= #{:MaxInclude}] read-string)
=
用作第一个键匹配函数,因为它在传递一个参数时总是返回true。第二个是利用集合是函数这一事实。此函数使用非优化递归,但调用堆栈的深度仅与匹配映射级别的数量相同
(defn update-all
"Like update-in except the second parameter is a vector of predicate
functions taking keys as arguments. Updates all values contained at a
matching path. Looks for keys in maps only."
[m [key-pred & key-preds] update-fn]
(if (map? m)
(let [matching-keys (filter key-pred (keys m))
f (fn [acc k]
(update-in acc [k] (if key-preds
#(update-all %
key-preds
update-fn)
update-fn)))]
(reduce f m matching-keys))
m))
(update-all a [= #{:MaxInclude}] read-string)