替换elisp中的关联列表中的项目

Mir*_*lov 24 lisp associative-array elisp

我在emacs lisp中有一个列表:

(setq a1
 '((:k1 . 1)
   (:k2 . 2)
   (:k3 . 3)))
Run Code Online (Sandbox Code Playgroud)

我想将值改为:k1到10,就像(:k1 . 10).我怎么做?

我试过(setf (assoc :k1 a1) '(:k1 . 10))- 它没用.

krz*_*z00 20

使用alist,你通常会在旧的前面添加一个新的缺点来"遮蔽"旧值,如下所示:

(add-to-list 'a1 '(:k1 10))
Run Code Online (Sandbox Code Playgroud)

这样做之后(assoc :k1 a1)将返回10.

如果您想"撤消"您的更改,请assoc再次返回旧值,请使用以下代码:

(setq a1 (delq (assoc :k1 a1) a1))
Run Code Online (Sandbox Code Playgroud)

这将删除FIRST匹配:k1a1.


Dal*_*ale 7

从Emacs 25.1开始,alist-get是一个地方表单,您可以这样做:

(setf (alist-get :k1 a1) 10)
Run Code Online (Sandbox Code Playgroud)


phi*_*ils 5

setf宏不知道assoc,但你仍然可以使用这种方法在一个稍微手动方式:

(let ((item (assoc :k1 a1)))
  (setf (car item) :k1)
  (setf (cdr item) 10))
Run Code Online (Sandbox Code Playgroud)

如果只需要为给定的汽车设置cdr(而不是替换两者),那么我们可以将其简化为:

(setf (cdr (assoc :k1 a1)) 10)
Run Code Online (Sandbox Code Playgroud)


小智 5

这个更短更简单的版本对我来说适用于 Emacs Lisp (MAC Lisp):

(setcdr (assoc :k1 a1) 10)
Run Code Online (Sandbox Code Playgroud)

或者,如果您碰巧使用的是 Common Lisp:

(rplacd (assoc :k1 a1) 10)
Run Code Online (Sandbox Code Playgroud)

(请注意, setcdr 和 rplad 在涉及返回哪个值时的行为可能略有不同。)