嵌套结构中的clojure重命名键

时间:2011-10-19 22:54:48

标签: clojure

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

{:data1 
    {:categories [
        {:name "abc" :id 234 :desc "whatever"} 
        {:name "def" :id 456 :desc "nothing"}]
    }
  :data2 {...}
  :data3 {...}
}

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

(rename-keys mymap {:data1 :d1})

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

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

3 个答案:

答案 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