clojure - Clojure - 使用 Spectre 转换嵌套数据结构,将一个节点替换为多个
问题描述
我正在使用Spectre来转换 Clojure 中的嵌套数据结构,但我还没有掌握它的窍门。特别是,我正在尝试创建一个转换,它将在任何深度找到一个与谓词匹配的项目,并将其替换为多个项目。
[:top
[:arbitrary 1 2
[:nesting
2
3
[:needle] ; <-- the thing to find
]]]
-->
[:top
[:arbitrary 1 2
[:nesting
2
3
[:n1] [:n2] [:n3] ; <-- 3 items inserted in the place of 1
]]]
我想不通的是如何将替换项拼接到父向量中,即如何将一项替换为三个项,而不是一项包含三个子项。
解决方案
我不知道如何使用 Spectre 来执行此操作,但这里有一个使用 clojure.zip 执行此操作的函数:
(defn splice-replace [zipper smap]
(loop [loc zipper]
(if (z/end? loc)
(z/root loc)
(recur
(z/next
(if-let [sub (smap (z/node loc))]
(reduce (comp z/right z/insert-right)
(z/replace loc (first sub))
(rest sub))
loc))))))
您可以使用数据结构的拉链和从要替换的值到要拼接到其位置的替换值序列的映射来调用它:
(def zipper
(z/vector-zip [:top
[:arbitrary 1 2
[:nesting 2 3 [:needle]]]]))
(splice-replace zipper {[:needle] [[:n1] [:n2] [:n3]]})
=> [:top [:arbitrary 1 2 [:nesting 2 3 [:n1] [:n2] [:n3]]]]
(splice-replace zipper {[:nesting 2 3 [:needle]] (range 3 10)})
=> [:top [:arbitrary 1 2 3 4 5 6 7 8 9]]
推荐阅读
- postgresql - 在 PostgreSQL 视图中显示最近 3 个日历年的记录
- javascript - document.ActiveElement 总是返回 body Angular
- authentication - 使用 gcloud auth 的用户凭据更持久?防止过期?
- python - 如何用角度计算长度
- java - 如何确定 Jenkins 使用什么来运行并将其指向正确的位置 (JAVA 11)
- matlab - Matlab底图或映射层显示国际日期变更线?
- oracle - ORACLE - 如何从一列中显示 3 个不同的值
- mfc - CMainFrame 的缓慢/延迟移动
- javascript - 未为用户定义的 musickit js 专辑
- azure - 同步现有帐户时,是否可以防止 UPN 的域更改为 onmicrosoft.com?