繁体   English   中英

如何更新Clojure的第一级

[英]how to update-in ingoring the first level in clojure

使用update-in时,我们需要提供元素的完整路径。 但是,如果我想更新第二级键为:MaxInclude的所有元素怎么办?

例如输入是

(def a  {:store {:type "varchar"},
 :amount {:nullable true, :length nil, :type "float", :MaxInclude "100.02"},
:unit {:type "int"},
:unit-uniform {:type "int" :MaxInclude "100"}
})

所需的输出是(根据theie类型将MaxInclude从字符串转换为float / int):

{:store {:type "varchar"},
 :amount {:nullable true, :length nil, :type "float", :MaxInclude 100.02},
:unit {:type "int"},
:unit-uniform {:type "int" :MaxInclude 100}
}

我当时想拥有一个像update-in这样的功能会很不错,它可以匹配键谓词功能而不是确切的键值。 这是我想出的:

(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。 第二个事实是集合是一个函数。 此函数使用非优化的递归,但调用堆栈的深度仅与匹配的映射级别的数目相同。

(into {}
      (map (fn [[k v]]
             {k (if (contains? v :MaxInclude)
                  (update-in v [:MaxInclude] read-string)
                  v)})
           a))

在这里,我正在映射键值对,并将每个键值对分解为k和v。然后update-in如果值包含:MaxInclude ,则对值使用update-in 最后,我倒从列表中对into哈希映射。

笔记:

  • 这将错误contains? 如果主地图的任何值都不是索引集合。
  • 我使用read-string作为将字符串转换为数字的便捷方法,就像Clojure阅读器在编译作为数字文字的字符串时所做的一样。 这种方法可能有缺点。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM