在elisp的

问题描述:

的值增加两个alists我点分对形式的两个列表:在elisp的

(((key1 . value1) . 5) 
((key2 . value2) . 7)) 

(((key2 . value2) . 3) 
((key3 . value3) . 9)) 

我想要的结果是一个关联表:

(((key1 . value1) . 5) 
((key2 . value2) . 10) 
((key3 . value3) . 9)) 

如何添加emacs lisp中的两个关联列表?换句话说,如果两个alist拥有相同的密钥,那么该密钥的值应该在结果alist中相加。

最可能的答案是一些elisp片段,但我也更喜欢一个漂亮的emacs宏。

使用CL模块中的溶液(与可读性,而不是效率记写的):

(require 'cl) 

(defun merge-alists (function default alist1 alist2) 
    (flet ((keys (alist) (mapcar #'car alist)) 
     (lookup (key alist) (or (cdr (assoc key alist)) default))) 
    (loop with keys = (union (keys alist1) (keys alist2) :test 'equal) 
      for k in keys collect 
      (cons k (funcall function (lookup k alist1) (lookup k alist2)))))) 

您可以使用它像这样:

elisp> (merge-alists '+ 0 '((foo . 1) (bar . 2)) '((foo . 11) (baz . 22))) 
((baz . 22) 
(foo . 12) 
(bar . 2)) 

elisp> (merge-alists '* 1 '((foo . 1) (bar . 2)) '((foo . 11) (baz . 22))) 
((baz . 22) 
(foo . 11) 
(bar . 2)) 

elisp> (merge-alists 'append '() '((foo a b) (bar c)) '((foo d e) (baz f g))) 
((baz f g) 
(foo a b d e) 
(bar c)) 

elisp> (setq my-alist1 '(((key1 . value1) . 5) ((key2 . value2) . 7))) 
(((key1 . value1) . 5) 
((key2 . value2) . 7)) 

elisp> (setq my-alist2 '(((key2 . value2) . 3) ((key3 . value3) . 9))) 
(((key2 . value2) . 3) 
((key3 . value3) . 9)) 

elisp> (merge-alists '+ 0 my-alist1 my-alist2) 
(((key3 . value3) . 9) 
((key1 . value1) . 5) 
((key2 . value2) . 10)) 

这可能是这样的:

(defun merge-alists (a1 a2) 
    (let ((ac (copy-alist a1))) 
     (dolist (x a2) 
     (when (null (assoc (car x) ac)) 
     (add-to-list 'ac x))) 
     ac)) 

它将返回从第二个列表中添加数据第一个列表的副本...

但是如果你会使用简单的append功能,然后重复拿下无论如何都不会被发现,因为函数通常会返回第一个已发现的值,而不是所有存在的值。

更新:对不起,无法正确读取的问题,另一种答案做正确,并在更普遍的方式。虽然,这是我此功能的变种,而无需使用CL包:

(defun merge-alists (a1 a2) 
    (let ((ac (copy-alist a1))) 
    (dolist (x a2) 
     (let ((r (assoc (car x) ac))) 
    (if (null r) 
     (add-to-list 'ac x) 
     (setf (cdr r) (+ (cdr x) (cdr r)))))) 
    ac)) 

附:在你的榜样,括号是不平衡:-)