Clojure中的Assoc-if

Odi*_*din 21 clojure

Clojure库中是否有"assoc-if"函数?即,如果值是真实的,则使用给定的键值更新地图.我试图找到这种效果的东西,但缺乏.

(defn assoc-if
  [m key value]
  (if value (assoc m key value) m))
Run Code Online (Sandbox Code Playgroud)

Cho*_*ser 29

如果目标是避免重复m,您可以使用conj:

(conj m (when value [key value]))
Run Code Online (Sandbox Code Playgroud)

...或Clojure 1.5的新线程宏:

(-> m
  (cond-> value (assoc key value)))
Run Code Online (Sandbox Code Playgroud)

如果避免重复使用m和实际上很重要value,那么你必须自己写或者到外面去clojure.core

  • 我认为`cond->`是一个很好的答案。 (2认同)

Leo*_*tny 11

assoc-ifClojure中没有内置函数,但你不是第一个需要它的人.检查此链接与实现assoc-if作家米勒:

(defn ?assoc
  "Same as assoc, but skip the assoc if v is nil"
  [m & kvs]
  (->> kvs
    (partition 2)
    (filter second)
    flatten
    (apply assoc m)))
Run Code Online (Sandbox Code Playgroud)

但是,既然flatten是递归的,最好用不合适的东西替换它(感谢kotarak提示).此实现的另一个问题是(apply assoc m)在空列表上将失败.因此,最好将其替换为:

(defn ?assoc
  "Same as assoc, but skip the assoc if v is nil"
  [m & kvs]
  (->> kvs
    (partition 2)
    (filter second)
    (map vec)
    (into m)))
Run Code Online (Sandbox Code Playgroud)

  • 我将用`vec`和`into`替换`flatten`和`assoc`。`(->> kvs(分区2)(第二过滤器)(map vec)(成m))。Flatten是递归的,很可能不是您想要的。 (2认同)