gpt4 book ai didi

Clojure:将函数应用于 map 的叶节点

转载 作者:行者123 更新时间:2023-12-01 12:30:02 24 4
gpt4 key购买 nike

如何将函数应用于(嵌套)映射的叶节点?例如,让我们有这张 map :

{:a 0
:b {:c 1}
:d [{:e 2} {:f 3}]}

假设我们要递增此映射中的所有叶节点并产生以下结果:

{:a 1
:b {:c 2}
:d [{:e 3} {:f 4}]}

目前,我正在考虑使用 this answer 中的 map zipper 并通过 clojure.zip 函数编辑 map 。但是,我不确定如何遍历 zipper 以及如何识别叶节点。我应该看哪些功能?有没有没有 zipper 的更简单的解决方案?

是否可以像下面这样工作(假设有一个 leaf-node? 谓词测试 zipper 中的位置是否是叶节点)?

(require '[clojure.zip :as zip])

(defn inc-leaf-nodes
[loc]
(if (zip/end? loc)
(zip/node loc)
(recur (zip/next (if (leaf-node? loc)
(zip/edit loc inc)
loc)))))

最佳答案

leaf-node? 函数可以在给定叶的适当定义的情况下实现,但建议的 inc-leaf-nodes 至少存在两个问题:

  • 您链接到的 zipper 实现使用映射条目作为节点,因此您不能简单地将 inc 传递给 zip/edit – 您必须将其包装在将其应用于值位置的辅助函数;

  • 那个 zipper 也不会将非映射值视为分支,因此它不会下降到向量 [{:e 3} {:f 4}] – 你会需要不同的 zipper 来解决这个问题。

假设叶子不是映射、集合或顺序集合,并且映射函数仅应用于映射中的值位置,您可以定义一个 map-leaves像这样的功能:

(defn map-leaves [f x]
(cond
(map? x) (persistent!
(reduce-kv (fn [out k v]
(assoc! out k (map-leaves f v)))
(transient {})
x))
(set? x) (into #{} (map #(map-leaves f %)) x)
(sequential? x) (into [] (map #(map-leaves f %)) x)
:else (f x)))

在 REPL 中:

(map-leaves inc {:a 0 :b {:c 1 :d [{:e 2} {:f 3}]}})
;= {:a 1, :b {:c 2, :d [{:e 3} {:f 4}]}}

(map-leaves inc {:a 0 :b {:c 1 :d [{:e 2} {:f 3} {:g #{1 2 3}}]}})
;= {:a 1, :b {:c 2, :d [{:e 3} {:f 4} {:g #{4 3 2}}]}}

关于Clojure:将函数应用于 map 的叶节点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35090158/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com