按elisp中的值添加两个alist

时间:2012-04-08 06:57:16

标签: emacs lisp elisp associative-array

我有两个表格的点对列表:

(((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宏。

2 个答案:

答案 0 :(得分:3)

使用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))

答案 1 :(得分:2)

可能是这样的:

(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))

P.S。在您的示例中,括号是不平衡的: - )