如何在 clojure 中添加或更新列表?
How to add or update a list in clojure?
我有这个功能,不知道怎么实现。我只知道怎么用concat,但是错了,因为它只会加,我还需要update
谁能帮帮我?
这是函数:
(defn update-env
[env-global key value]
(if (and (list? value) (= (first value) '*error*))
env-global
(concat env-global (list key value))))
这是我需要的代码 运行:
(update-env '(+ add - sub x 1 y 2) 'x 3)
这是它应该给出的结果:
(+ 添加 - 子 x 3 y 2)
提前致谢!
您可以将 env-global
表示为哈希映射并使用 assoc
进行更新:
(defn update-env [env-global key value]
(if (and (list? value)
(= (first value) '*error*))
env-global
(assoc env-global key value)))
(update-env '{+ add - sub x 1 y 2} 'x 3)
或者您可以使用列表并将其转换为散列映射并返回(已编辑):
(defn env->map [env]
(apply hash-map env))
(defn map->env [m]
(->> m
(apply list)
(apply concat)))
(-> (env->map '(+ add - sub x 1 y 2))
(update-env 'x 3)
(map->env))
诀窍是对集合的元素进行成对操作,类似于常见的 lisp plist
。你可以编这样的东西:
(defn plist-assoc [key new-val plist]
(->> plist
(partition 2)
(mapcat (fn [[k v]] [k (if (= k key) new-val v)]))))
user> (plist-assoc 'x 3 '(+ add - sub x 1 y 2))
;;=> (+ add - sub x 3 y 2)
user> (plist-assoc 'z 3 '(+ add - sub x 1 y 2))
;;=> (+ add - sub x 1 y 2)
所以你的函数看起来像这样:
(defn update-env [env-global key value]
(if (and (list? value) (= (first value) '*error*))
env-global
(plist-assoc key value env-global)))
user> (update-env '(+ add - sub x 1 y 2) 'x 3)
;;=> (+ add - sub x 3 y 2)
更新
如果你需要更新或插入新值,你可以使用类似这样的东西:
(defn assoc-plist2 [key new-val plist]
(let [[l r] (->> plist
(partition 2)
(split-with (comp nil? #{key} first)))]
(apply concat `(~@l ~[key new-val] ~@(rest r)))))
user> (assoc-plist2 'x 10 '(+ add - sub x 1 y 2))
;;=> (+ add - sub x 10 y 2)
user> (assoc-plist2 'z 10 '(+ add - sub x 1 y 2))
;;=> (+ add - sub x 1 y 2 z 10)
我有这个功能,不知道怎么实现。我只知道怎么用concat,但是错了,因为它只会加,我还需要update
谁能帮帮我?
这是函数:
(defn update-env
[env-global key value]
(if (and (list? value) (= (first value) '*error*))
env-global
(concat env-global (list key value))))
这是我需要的代码 运行: (update-env '(+ add - sub x 1 y 2) 'x 3)
这是它应该给出的结果: (+ 添加 - 子 x 3 y 2)
提前致谢!
您可以将 env-global
表示为哈希映射并使用 assoc
进行更新:
(defn update-env [env-global key value]
(if (and (list? value)
(= (first value) '*error*))
env-global
(assoc env-global key value)))
(update-env '{+ add - sub x 1 y 2} 'x 3)
或者您可以使用列表并将其转换为散列映射并返回(已编辑):
(defn env->map [env]
(apply hash-map env))
(defn map->env [m]
(->> m
(apply list)
(apply concat)))
(-> (env->map '(+ add - sub x 1 y 2))
(update-env 'x 3)
(map->env))
诀窍是对集合的元素进行成对操作,类似于常见的 lisp plist
。你可以编这样的东西:
(defn plist-assoc [key new-val plist]
(->> plist
(partition 2)
(mapcat (fn [[k v]] [k (if (= k key) new-val v)]))))
user> (plist-assoc 'x 3 '(+ add - sub x 1 y 2))
;;=> (+ add - sub x 3 y 2)
user> (plist-assoc 'z 3 '(+ add - sub x 1 y 2))
;;=> (+ add - sub x 1 y 2)
所以你的函数看起来像这样:
(defn update-env [env-global key value]
(if (and (list? value) (= (first value) '*error*))
env-global
(plist-assoc key value env-global)))
user> (update-env '(+ add - sub x 1 y 2) 'x 3)
;;=> (+ add - sub x 3 y 2)
更新 如果你需要更新或插入新值,你可以使用类似这样的东西:
(defn assoc-plist2 [key new-val plist]
(let [[l r] (->> plist
(partition 2)
(split-with (comp nil? #{key} first)))]
(apply concat `(~@l ~[key new-val] ~@(rest r)))))
user> (assoc-plist2 'x 10 '(+ add - sub x 1 y 2))
;;=> (+ add - sub x 10 y 2)
user> (assoc-plist2 'z 10 '(+ add - sub x 1 y 2))
;;=> (+ add - sub x 1 y 2 z 10)