假设我有一个嵌套结构,如下所示:
{:data1
{:categories [
{:name "abc" :id 234 :desc "whatever"}
{:name "def" :id 456 :desc "nothing"}]
}
:data2 {...}
:data3 {...}
}
我需要转换地图中的关键名称。我可以像这样转换顶级键:
(rename-keys mymap {:data1 :d1})
但我不确定如何重命名嵌套在数据结构中更深入的键(假设我想将:desc字段重命名为:description)。
我很确定拉链是答案,但不能弄清楚如何做,或者是否有更简单的方法。
答案 0 :(得分:8)
与Brian Carper的解决方案相同,但walk命名空间已经具有用于此目的的特定功能。所有级别的所有键都会被更改,无论是嵌套在任何类型的集合中还是seq。
(:use 'clojure.walk)
(def x
{:data1
{:categories
[{:desc "whatever", :name "abc", :id 234}
{:desc "nothing", :name "def", :id 456}]},
:data2
{:categories
[{:desc "whatever", :name "abc", :id 234}
{:desc "nothing", :name "def", :id 456}]}})
(postwalk-replace {:desc :something} x)
{:data1
{:categories
[{:something "whatever", :name "abc", :id 234}
{:something "nothing", :name "def", :id 456}]},
:data2
{:categories
[{:something "whatever", :name "abc", :id 234}
{:something "nothing", :name "def", :id 456}]}}
答案 1 :(得分:6)
postwalk
一般来说是一个非常沉重的大锤,虽然它看起来像你可能需要的原始问题。在许多情况下,您可以使用update-in
:
user> (let [m {:foo {:deep {:bar 1 :baz 2}}}]
(update-in m [:foo :deep] clojure.set/rename-keys {:baz :periwinkle}))
{:foo {:deep {:periwinkle 2, :bar 1}}}
答案 2 :(得分:3)
如果要重命名所有:desc
个密钥,无论它们位于哪个嵌套级别,这都可能有效。如果您只想在某个嵌套级别重命名:desc
个键,则需要稍微复杂一些的东西。
这只能起作用,因为如果第一个参数不是一个映射,clojure.set/rename-keys
当前什么也不做(返回它的第一个参数未触及)。
user> (require '[clojure [set :as set] [walk :as walk]])
nil
user> (def x {:data1
{:categories
[{:desc "whatever", :name "abc", :id 234}
{:desc "nothing", :name "def", :id 456}]},
:data2
{:categories
[{:desc "whatever", :name "abc", :id 234}
{:desc "nothing", :name "def", :id 456}]}})
#'user/x
user> (walk/postwalk #(set/rename-keys % {:desc :description :id :ID}) x)
{:data1
{:categories
[{:name "abc", :ID 234, :description "whatever"}
{:name "def", :ID 456, :description "nothing"}]},
:data2
{:categories
[{:name "abc", :ID 234, :description "whatever"}
{:name "def", :ID 456, :description "nothing"}]}}
nil