附加到嵌套的关联结构中

时间:2011-06-28 03:42:28

标签: clojure

我有一个我在REPL创建的结构,

{1 {10 {:id 101, :name "Paul"}, 
    20 {}}, 
2 {30 {}, 40 {}}, 
3 {50 {}, 60 {}}}

我想在键1上添加一个新的k v,这样得到的结构就像这样,

{1 {10 {:id 101, :name "1x2"}, 20 {}, 11 {:id 102, :name "Ringo"}},
 2 {30 {}, 40 {}}, 3 {50 {}, 60 {}}}.

我刚刚发现了get-in update-in和assoc-in来处理这些嵌套结构,但无法弄清楚如何在元素中添加新元素。在我的应用程序中,这全部包含在ref中并使用dosync / alter进行更新,但是现在,我只想在REPL中执行此操作。

也许我一直在考虑这个问题太久了,但任何使用assoc或assoc-in的尝试都会改变已经存在的东西,并且不会附加新的元素。

2 个答案:

答案 0 :(得分:7)

鉴于您的输入

(def input
  {1 {10 {:id 101 :name "Paul"}
      20 {}}
   2 {30 {} 40 {}}
   3 {50 {} 60 {}}})

您可以使用assoc-in将一个元素添加到嵌套映射中,使用键1,如下所示:

(assoc-in input [1 11] {:id 102 :name "Ringo"})

产生

{1 {10 {:id 101 :name "Paul"}
    11 {:id 102 :name "Ringo"}
    20 {}}
 2 {30 {} 40 {}}
 3 {50 {} 60 {}}}

Assoc-in不需要一直指向结构的最深层。

如果您使用两个来自assoc-in的调用,您可以使用第二个调用根据您的示例将名称“Paul”更改为“1x2”:

(assoc-in
  (assoc-in input [1 11] {:id 102 :name "Ringo"})
  [1 10 :name] "1x2"))

返回

{1 {10 {:id 101 :name "1x2"}
    11 {:id 102 :name "Ringo"}
    20 {}}
 2 {30 {} 40 {}}
 3 {50 {} 60 {}}}

答案 1 :(得分:1)

如果你必须指向现有节点,那么你仍然可以做到这一点:

(update-in input [1] assoc 11 
  {:id 102 :name "Ringo"})