我想在clojure的大地图中更改某些键。 这些密钥可以出现在地图中的任何级别,但始终位于必需密钥
中我正在考虑使用camel-snake-kebab库,但是需要它才能在必需键映射中仅更改给定的一组键。如果在json或地图中进行更改无关紧要
(def my-map {:allow_kebab_or-snake {:required-key {:must_be_kebab ""}}
:allow_kebab_or-snake2 {:optional-key {:required-key {:must_be_kebab ""}}}})
目前使用/ walk / postwalk-replace但担心它可能会更改未嵌套在:required-key map中的键
(walk/postwalk-replace {:must_be_kebab :must-be-kebab} my-map))
答案 0 :(得分:0)
偏离主题:上面的地图不正确(有两个相同的键:allow_kebab_or_snake - 我假设你只是强调了这一点而没有显示实际的例子:))
postwalk-replace将用值替换任何出现的键。
所以,如果你知道确切的map结构,你可以先用get-in选择你的子结构,然后使用postwalk-replace:
(walk/postwalk-replace {:must_be_kebab :mus-be-kebab}
(get-in my-map [:allow_kebab_or_snake :required-key]))
但是你必须将assoc
这个放入你的初始地图中。
如果交错DS过于复杂,您还应该考虑walk函数并构建自己的特定算法。
答案 1 :(得分:0)
这是一个解决方案。由于您需要控制转换何时执行/不执行,因此您不能只使用postwalk
。您需要实现自己的递归并从非转换中更改上下文 - >找到你的病情后转换。
(ns tst.clj.core
(:use clj.core clojure.test tupelo.test)
(:require
[clojure.string :as str]
[clojure.pprint :refer [pprint]]
[tupelo.core :as t]
[tupelo.string :as ts]
))
(t/refer-tupelo)
(t/print-versions)
(def my-map
{:allow_kebab_or-snake {:required-key {:must_be_kebab ""}}
:allow_kebab_or-snake2 {:optional-key {:required-key {:must_be_kebab ""}}}})
(defn children->kabob? [kw]
(= kw :required-key))
(defn proc-child-maps
[ctx map-arg]
(apply t/glue
(for [curr-key (keys map-arg)]
(let [curr-val (grab curr-key map-arg)
new-ctx (if (children->kabob? curr-key)
(assoc ctx :snake->kabob true)
ctx)
out-key (if (grab :snake->kabob ctx)
(ts/kw-snake->kabob curr-key)
curr-key)
out-val (if (map? curr-val)
(proc-child-maps new-ctx curr-val)
curr-val)]
{out-key out-val}))))
(defn nested-keys->snake
[arg]
(let [ctx {:snake->kabob false}]
(if (map? arg)
(proc-child-maps ctx arg)
arg)))
最终结果显示在单元测试中:
(is= (nested-keys->snake my-map)
{:allow_kebab_or-snake
{:required-key
{:must-be-kebab ""}},
:allow_kebab_or-snake2
{:optional-key
{:required-key
{:must-be-kebab ""}}}} ))
对于这个解决方案,我使用了一些便利函数documentation
答案 2 :(得分:0)
只是左侧的字段建议,可能有效,也可能无效。这是在处理SQL数据库时可能出现的问题,因为' - '被视为保留字,不能在标识符中使用。但是,在使用clojure时,通常在关键字中使用“ - ”。在clojure中使用SQL时使用的许多抽象层将映射作为预处理语句等的参数/绑定。
理想情况下,需要的是另一层抽象,它根据你要去的方向(即sql或sql)根据需要在kebab和snake case之间进行转换。这种方法的优势在于您无需通过地图进行转换 - 您可以在需要时“即时”进行转换。
查看https://pupeno.com/2015/10/23/automatically-converting-case-between-sql-and-clojure/