Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/file/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Clojure:将函数应用于映射的叶节点_Clojure - Fatal编程技术网

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

Clojure:将函数应用于映射的叶节点,clojure,Clojure,如何将函数应用于(嵌套)贴图的叶节点?例如,让我们看一下这张地图: {:a 0 :b {:c 1} :d [{:e 2} {:f 3}]} 假设我们希望增加此映射中的所有叶节点,并生成以下结果: {:a 1 :b {:c 2} :d [{:e 3} {:f 4}]} 目前,我正在考虑使用地图拉链,并通过clojure.zip函数编辑地图。但是,我不确定如何遍历拉链以及如何识别叶节点。我应该看什么函数?有没有一个没有拉链的更简单的解决方案 是否可以进行类似以下工作(如果存在叶节点?谓词

如何将函数应用于(嵌套)贴图的叶节点?例如,让我们看一下这张地图:

{:a 0
 :b {:c 1}
 :d [{:e 2} {:f 3}]}
假设我们希望增加此映射中的所有叶节点,并生成以下结果:

{:a 1
 :b {:c 2}
 :d [{:e 3} {:f 4}]}
目前,我正在考虑使用地图拉链,并通过
clojure.zip
函数编辑地图。但是,我不确定如何遍历拉链以及如何识别叶节点。我应该看什么函数?有没有一个没有拉链的更简单的解决方案

是否可以进行类似以下工作(如果存在
叶节点?
谓词测试zippers中的位置是否为叶节点)


如果叶的定义合适,可以实现
叶节点?
功能,但建议的
inc叶节点
至少存在两个问题:

  • 您链接到的zipper实现使用地图条目作为节点,因此您不能简单地将
    inc
    传递到
    zip/edit
    ——您必须将其包装在一个助手函数中,该函数将在值位置应用它

  • 该拉链也不会将非映射值视为分支,因此它不会下降到向量
    [{:e3}{:f4}]
    ——您需要一个不同的拉链来解决这个问题

假设叶不是映射、集合或顺序集合,且映射函数仅应用于映射中的值位置,则可以定义如下的
映射叶
函数:

(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.zip
对这项任务来说是一种过分的手段,还是根本不是一个合适的解决方案?@jindrichm不必担心。只是编辑了答案来解释为什么你链接的拉链不起作用。如果您想在以后的其他转换中使用它,您可以考虑实现一个不同的zipper,但是如果您只对
map leaves
感兴趣,以上可能是更简单的方法。(顺便说一句,
clojure.walk
是解决此问题的最简单方法,该函数也将应用于关键位置。)
(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}}]}}