Map “的惯用方式”;更新「;Clojure地图中的给定密钥?

Map “的惯用方式”;更新「;Clojure地图中的给定密钥?,map,clojure,merge,Map,Clojure,Merge,假设我们有一张类似以下内容的地图: (def m {:a {:foo "bar"}}) >>> d = {'a': {'foo': 'bar'}} >>> d['a'].update({'baz': 'qux'}) >>> d {'a': {'foo': 'bar', 'baz': 'qux'}} 现在,我们想用一些新值更新m中的key:a: (def vs {:baz "qux"}) 如果这是Python,我们可以执行以下操作: (d

假设我们有一张类似以下内容的地图:

(def m {:a {:foo "bar"}})
>>> d = {'a': {'foo': 'bar'}}
>>> d['a'].update({'baz': 'qux'})
>>> d
{'a': {'foo': 'bar', 'baz': 'qux'}}
现在,我们想用一些新值更新m中的key:a:

(def vs {:baz "qux"})
如果这是Python,我们可以执行以下操作:

(def m {:a {:foo "bar"}})
>>> d = {'a': {'foo': 'bar'}}
>>> d['a'].update({'baz': 'qux'})
>>> d
{'a': {'foo': 'bar', 'baz': 'qux'}}
我发现最简单的Clojure等价物是定义如下函数:

(defn update-key
  "
  Updates a given key `k` over a map `m` with a map of values `vs`.
  "
  [k m vs]
  (assoc m k (merge (k m) vs)))
然后调用如下所示:

(update-key :a m vs)
; => {:a {:foo "bar" :baz "qux"}}

因此,我的问题是:实现与Python dicts提供的
update()
方法相同功能的最惯用和正确的方法是什么?

我想您正在寻找:

与此类似,可能也值得一看。这实际上可能更接近您的Python示例:

(def m {:a {:foo "bar"}})
(def vs {:baz "qux"})

(update-in m [:a] merge vs)
; => {:a {:foo "bar", :baz "qux"}}

更新:

即使键是一个变量值(不是编译时常数),您仍然可以通过将变量放入向量中来使用
updatein
assoc in

(def m {:a {:foo "bar"}})
(def k' :baz)
(def v' "qux")

(assoc-in m [:a k'] v')
; => {:a {:foo "bar", :baz "qux"}}
还可以通过编程方式构建关键点向量:

(def m {:a {:foo "bar"}})
(def k' :baz)
(def v' "qux")

(let [ks (conj [:a] k')]
  (assoc-in m ks v'))
; => {:a {:foo "bar", :baz "qux"}}

啊,太好了,
updatein
应该完全符合我的要求(
assoc in
会更好,但我不知道
vs
中的关键字名称)。出于某种原因,我没有发现这些文档特别说明:我在中读到了
assoc和
updatein
,但不知道如何合并到正确的键中。谢谢@maxcountryman-静态地不知道键/值不是问题。有关使用非静态键的示例,请参见我的更新。感谢更新。对于我正在做的事情来说,与
中的
更新相比,这可能有点麻烦。如果我必须在
中使用
assoc来分隔键和值,那么代码将不如在
中使用
update简洁。但很高兴看到它可以做到!