嵌套结构中的clojure重命名键

Kev*_*vin 8 clojure

假设我有一个嵌套结构,如下所示:

{:data1 
    {:categories [
        {:name "abc" :id 234 :desc "whatever"} 
        {:name "def" :id 456 :desc "nothing"}]
    }
  :data2 {...}
  :data3 {...}
}
Run Code Online (Sandbox Code Playgroud)

我需要转换地图中的关键名称.我可以像这样转换顶级键:

(rename-keys mymap {:data1 :d1})
Run Code Online (Sandbox Code Playgroud)

但我不确定如何重命名嵌套在数据结构中更深入的键(假设我想将:desc字段重命名为:description).

我很确定拉链是答案,但不能弄清楚如何做到这一点,或者是否有更简单的方法.

Nie*_*lsK 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}]}}
Run Code Online (Sandbox Code Playgroud)


ama*_*loy 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}}}
Run Code Online (Sandbox Code Playgroud)