我正在寻找一种方法从关联列表中“弹出”一个元素,换句话说就是“破坏性”的关联:
(setq alist '((a . 1) (b . 2))
(assoc-pop 'a alist) ;; -> (a . 1)
;; alist -> ((b . 2))
elisp线束中是否有任何功能? 获得symilar功能最优雅的方法是什么? (不确定这种“副作用”是一种很好的做法,即使有可能!)
答案 0 :(得分:3)
我没有注意到这样的内置运算符,但我认为你可以很快得到这个功能:
(defmacro assoc-pop (key alist)
`(let ((result (assoc ,key ,alist)))
(setq ,alist (delete result ,alist))
result))
答案 1 :(得分:1)
assq-delete-all
接近你想要的。它按对象标识(eq
)查找元素,而不是按值相等(equal
)查找元素。它删除所有匹配的元素,而不仅仅是第一个。它返回修改后的列表。您可以调整此函数的代码以执行您想要的操作。 (但如果您要在循环中拨打assoc-pop
,并且所有密钥都是符号,那么assq-delete-all
可以满足您的所有要求。)
请注意"a"
和'a
是完全不同的对象:第一个是字符串,第二个是符号。所以你的第二行应该是(assoc-pop 'a alist)
。
但实际上,调用(assoc-pop 'a alist)
无效(除非assoc-pop
是宏),因为它无法删除列表中的第一个元素。您可以创建一个以符号作为参数的函数,并根据add-to-list
的模型修改符号值的列表。您可以将其称为(assoc-pop 'a 'alist)
。