【问题标题】:Recursively mutating values in a map of maps with Specter使用 Spectre 递归地改变地图中的值
【发布时间】:2020-04-05 05:24:48
【问题描述】:

在这里完成 Clojure 新手。这是一个简单的问题,但我似乎无法理解:

鉴于我有一个未知深度的嵌套 hasmap,我如何使用 Spectre 的 transform() 来改变数据结构的值?我想这里需要一个递归路径,但我无法让它工作。一个可行的例子是我所追求的,不幸的是,文档中没有。

(在递归映射中有一个 example 用于 set-val,但我不知道如何将其转换为转换用例)

编辑:要求提供更多详细信息,因此它们是: 我对可以改变嵌套映射的所有值的转换形式感兴趣 - 任何深度)。例如,此转换将能够递增以下映射(以及任何其他嵌套映射)中的所有值:

{:a 1 :b {:c 2 :d {:e 3}}} 
AND
{:a 1 :b {:c 2}}
AND
{:a 1}

我感兴趣的代码行可能看起来像这样:

(transform <missing selector here> inc data)

【问题讨论】:

  • 即使你没有让它工作,你的代码也会帮助我们了解你想要做什么并从那里开始工作。
  • @cfrick 我添加了更多细节。我认为这对于任何了解幽灵的人来说都应该足够清楚。没有太多代码可以展示——这在 clojure 中很典型
  • 最简单的是(transform (walker number?) inc {:a 1 :b {:c 2 :d {:e 3}}})。它可能过于笼统,但它仍然解决了嵌套映射(以​​及任何嵌套结构)的情况

标签: recursion clojure specter


【解决方案1】:

使用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)

【讨论】:

    【解决方案2】:

    请务必始终研究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 感兴趣,它允许您检查从根节点到当前节点的路径上的所有项目。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-06-06
      • 2011-02-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-10
      相关资源
      最近更新 更多