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

时间:2012-04-08 13:33:46

标签: lisp elisp associative-array

我在emacs lisp中有一个alist:

(setq a1
 '((:k1 . 1)
   (:k2 . 2)
   (:k3 . 3)))

我希望将值k1更改为10,如(:k1 . 10)。我该怎么做?

我尝试了(setf (assoc :k1 a1) '(:k1 . 10)) - 它没有用。

6 个答案:

答案 0 :(得分:20)

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

(add-to-list 'a1 '(:k1 10))

执行此操作后,(assoc :k1 a1)将返回10.

如果您要“撤消”更改,assoc再次返回旧值,请使用以下代码:

(setq a1 (delq (assoc :k1 a1) a1))

这将从:k1移除a1第一次匹配。

答案 1 :(得分:7)

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

(setf (alist-get :k1 a1) 10)

答案 2 :(得分:5)

setf宏不了解assoc,但您仍然可以稍微以手动方式使用该方法:

(let ((item (assoc :k1 a1)))
  (setf (car item) :k1)
  (setf (cdr item) 10))

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

(setf (cdr (assoc :k1 a1)) 10)

答案 3 :(得分:4)

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

(setcdr (assoc :k1 a1) 10)

或者,如果你碰巧使用Common Lisp:

(rplacd (assoc :k1 a1) 10)

(请注意,setcdr和rplacd在返回哪个值时可能会略有不同。)

答案 4 :(得分:1)

assq-delete-all

怎么样?
(setq sql-product-alist
      (cons '(ms-tsql :server ....)
            (assq-delete-all 'ms-tsql sql-product-alist)))

答案 5 :(得分:1)

这是基于gavenkoa建议的功能 -

(defun alist-set (alist-symbol key value)
  "Set KEY to VALUE in alist ALIST-SYMBOL."
  (set alist-symbol
        (cons (list key value) 
              (assq-delete-all key (eval alist-symbol)))))

用法 -

(let ((foo '((a 1) (b 2))))
  (alist-set 'foo 'a 3)
  foo) ; => ((a 3) (b 2))
相关问题