如何更新clojure的第一级

如何更新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"} })

在中使用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"}
})
所需的输出是(根据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)