Clojure 如果集合2没有',则将集合1中的项目添加到集合2;不包含集合1中的项

Clojure 如果集合2没有',则将集合1中的项目添加到集合2;不包含集合1中的项,clojure,Clojure,我有两张地图: (def people{:1“约翰”:2“保罗”:3“林戈”:4“乔治”}) 我想循环查看人员,并将[:data:members]中不存在的任何成员添加到波段,结果是: (def band {:data {:members {:1 {:id 1 :name "John"} :2 {:id 2 :name "Paul"} :3 {:id 3 :name "Ringo"} :4 {:id 4 :name "Ge

我有两张地图:

(def people{:1“约翰”:2“保罗”:3“林戈”:4“乔治”})

我想循环查看
人员
,并将
[:data:members]
中不存在的任何成员添加到
波段
,结果是:

(def band 
  {:data 
    {:members 
      {:1 {:id 1 :name "John"} 
       :2 {:id 2 :name "Paul"}
       :3 {:id 3 :name "Ringo"}
       :4 {:id 4 :name "George"}}}})
以下是我尝试过的:

(for [[id name] people]
  (when-not
    (contains? (get-in band [:data :members]) id)
    (assoc-in band [:data :members id] {:id id :name name})))
这将产生:

({:data 
   {:members 
     {:4 {:id :4, :name "George"}, 
      :1 {:name "John", :id 1}, 
      :2 {:name "Paul", :id 2}}}} 
 nil 
 nil 
 {:data 
   {:members 
     {:1 {:name "John", :id 1}, 
      :2 {:name "Paul", :id 2}, 
      :3 {:id :3, :name "Ringo"}}}})

我不知道为什么我会得到一个似乎是
波段
每个突变的列表。我做错了什么?我如何才能将
中缺少的成员添加到
乐队[:data:members]

要学究,你不会得到乐队的任何突变。事实上,Clojure最重要的特性之一是标准类型是不可变的,主收集操作返回一个修改后的副本而不更改原始类型

此外,Clojure中的
for
不是循环,而是列表理解。这就是为什么它总是返回每个步骤的序列。因此,您没有一步一步地修改输入,而是对每个步骤的输入进行了新的更改,每个步骤都源自不可变的原始输入

基于值序列生成输入的一系列更新副本的标准构造是
reduce
,它将新版本的累加器和列表中的每个元素传递给函数

最后,您误解了
:keyword
语法的作用——构造映射键不需要在项前加上:前缀——几乎任何clojure值都是映射的有效键,而关键字只是一种方便的习惯用法

user=> (def band 
            {:data 
              {:members 
                {1 {:id 1 :name "John"} 
                 2 {:id 2 :name "Paul"}}}})
#'user/band
user=> (def people {1 "John" 2 "Paul" 3 "Ringo" 4 "George"})
#'user/people
user=>  (pprint
         (reduce (fn [band [id name :as person]]
                    (if-not (contains? (get-in band [:data :members]) id)
                      (assoc-in band [:data :members id] {:id id :name name})
                      band))
                  band
                  people))
{:data
 {:members
  {3 {:id 3, :name "Ringo"},
   4 {:id 4, :name "George"},
   1 {:name "John", :id 1},
   2 {:name "Paul", :id 2}}}}
nil

您可能会注意到传递给
reduce
fn的主体与
理解的
主体基本相同。不同之处在于,我使用了
if not
,而不是
when not
,它允许我们传播累加器(这里称为
,与输入相同),而不管是否制作了新版本的累加器。

为了学究,你没有得到带的任何突变。事实上,Clojure最重要的特性之一是标准类型是不可变的,主收集操作返回一个修改后的副本而不更改原始类型

此外,Clojure中的
for
不是循环,而是列表理解。这就是为什么它总是返回每个步骤的序列。因此,您没有一步一步地修改输入,而是对每个步骤的输入进行了新的更改,每个步骤都源自不可变的原始输入

基于值序列生成输入的一系列更新副本的标准构造是
reduce
,它将新版本的累加器和列表中的每个元素传递给函数

最后,您误解了
:keyword
语法的作用——构造映射键不需要在项前加上:前缀——几乎任何clojure值都是映射的有效键,而关键字只是一种方便的习惯用法

user=> (def band 
            {:data 
              {:members 
                {1 {:id 1 :name "John"} 
                 2 {:id 2 :name "Paul"}}}})
#'user/band
user=> (def people {1 "John" 2 "Paul" 3 "Ringo" 4 "George"})
#'user/people
user=>  (pprint
         (reduce (fn [band [id name :as person]]
                    (if-not (contains? (get-in band [:data :members]) id)
                      (assoc-in band [:data :members id] {:id id :name name})
                      band))
                  band
                  people))
{:data
 {:members
  {3 {:id 3, :name "Ringo"},
   4 {:id 4, :name "George"},
   1 {:name "John", :id 1},
   2 {:name "Paul", :id 2}}}}
nil

您可能会注意到传递给
reduce
fn的主体与
理解的
主体基本相同。不同之处在于,我使用了
if not
,而不是
when not
,它允许我们传播累加器(这里称为
,与输入相同),而不管是否制作了新版本的累加器。

为了学究,你没有得到带的任何突变。事实上,Clojure最重要的特性之一是标准类型是不可变的,主收集操作返回一个修改后的副本而不更改原始类型

此外,Clojure中的
for
不是循环,而是列表理解。这就是为什么它总是返回每个步骤的序列。因此,您没有一步一步地修改输入,而是对每个步骤的输入进行了新的更改,每个步骤都源自不可变的原始输入

基于值序列生成输入的一系列更新副本的标准构造是
reduce
,它将新版本的累加器和列表中的每个元素传递给函数

最后,您误解了
:keyword
语法的作用——构造映射键不需要在项前加上:前缀——几乎任何clojure值都是映射的有效键,而关键字只是一种方便的习惯用法

user=> (def band 
            {:data 
              {:members 
                {1 {:id 1 :name "John"} 
                 2 {:id 2 :name "Paul"}}}})
#'user/band
user=> (def people {1 "John" 2 "Paul" 3 "Ringo" 4 "George"})
#'user/people
user=>  (pprint
         (reduce (fn [band [id name :as person]]
                    (if-not (contains? (get-in band [:data :members]) id)
                      (assoc-in band [:data :members id] {:id id :name name})
                      band))
                  band
                  people))
{:data
 {:members
  {3 {:id 3, :name "Ringo"},
   4 {:id 4, :name "George"},
   1 {:name "John", :id 1},
   2 {:name "Paul", :id 2}}}}
nil

您可能会注意到传递给
reduce
fn的主体与
理解的
主体基本相同。不同之处在于,我使用了
if not
,而不是
when not
,它允许我们传播累加器(这里称为
,与输入相同),而不管是否制作了新版本的累加器。

为了学究,你没有得到带的任何突变。事实上,Clojure最重要的特性之一是标准类型是不可变的,主收集操作返回一个修改后的副本而不更改原始类型

此外,Clojure中的
for
不是循环,而是列表理解。这就是为什么它总是返回每个步骤的序列。因此,您没有一步一步地修改输入,而是对每个步骤的输入进行了新的更改,每个步骤都源自不可变的原始输入

基于值序列生成输入的一系列更新副本的标准构造是
reduce
,它将新版本的累加器和列表中的每个元素传递给函数

最后,您误解了
:keyword
语法的作用-构造映射键时不需要在项前加:前缀-几乎任何clojure值都是映射的有效键,而keyw