使用 Spectre 递归地改变地图中的值
Recursively mutating values in a map of maps with Specter
完整的 Clojure 新手在这里。这是一个简单的问题,但我似乎无法理解:
鉴于我有一个未知深度的嵌套 hasmap,我如何使用 Spectre 的 transform() 来改变数据结构的值?我想这里需要一个递归路径,但我无法让它工作。一个工作示例就是我所追求的,不幸的是,文档中没有。
(在递归映射上有一个用于 set-val 的 example,但我不知道如何将其转换为转换用例)
编辑:要求提供更多详细信息,因此它们是:
我对一种变换形式很感兴趣,它可以改变嵌套地图的所有值——任何深度)。例如,此转换将能够增加以下映射(以及任何其他嵌套映射)中的所有值:
{:a 1 :b {:c 2 :d {:e 3}}}
AND
{:a 1 :b {:c 2}}
AND
{:a 1}
我感兴趣的代码行可能看起来像这样:
(transform <missing selector here> inc data)
使用 linked example:
(def MAP-NODES
(recursive-path [] p
(if-path map?
(continue-then-stay MAP-VALS p))))
(transform [MAP-NODES MAP-VALS number?] inc data)
一定要经常学习Clojure CheatSheet。对于这么简单的事情,使用 clojure.walk/postwalk
可能是最简单的
(ns tst.demo.core
(:use tupelo.core tupelo.test)
(:require [clojure.walk :as walk]))
(dotest
(let [data {:a 1 :b {:c 2 :d {:e 3}}}
result (walk/postwalk (fn [item]
(if (int? item)
(inc item)
item))
data)]
(is= result {:a 2, :b {:c 3, :d {:e 4}}})))
对于更高级的问题,您可能对函数 walk-with-parents 感兴趣,它允许您检查从根节点到当前节点的路径上的所有项目。
完整的 Clojure 新手在这里。这是一个简单的问题,但我似乎无法理解:
鉴于我有一个未知深度的嵌套 hasmap,我如何使用 Spectre 的 transform() 来改变数据结构的值?我想这里需要一个递归路径,但我无法让它工作。一个工作示例就是我所追求的,不幸的是,文档中没有。
(在递归映射上有一个用于 set-val 的 example,但我不知道如何将其转换为转换用例)
编辑:要求提供更多详细信息,因此它们是: 我对一种变换形式很感兴趣,它可以改变嵌套地图的所有值——任何深度)。例如,此转换将能够增加以下映射(以及任何其他嵌套映射)中的所有值:
{:a 1 :b {:c 2 :d {:e 3}}}
AND
{:a 1 :b {:c 2}}
AND
{:a 1}
我感兴趣的代码行可能看起来像这样:
(transform <missing selector here> inc data)
使用 linked example:
(def MAP-NODES (recursive-path [] p (if-path map? (continue-then-stay MAP-VALS p))))
(transform [MAP-NODES MAP-VALS number?] inc data)
一定要经常学习Clojure CheatSheet。对于这么简单的事情,使用 clojure.walk/postwalk
(ns tst.demo.core
(:use tupelo.core tupelo.test)
(:require [clojure.walk :as walk]))
(dotest
(let [data {:a 1 :b {:c 2 :d {:e 3}}}
result (walk/postwalk (fn [item]
(if (int? item)
(inc item)
item))
data)]
(is= result {:a 2, :b {:c 3, :d {:e 4}}})))
对于更高级的问题,您可能对函数 walk-with-parents 感兴趣,它允许您检查从根节点到当前节点的路径上的所有项目。