The Kitchen Sink and Other Oddities

Atabey Kaygun

Merging Association Lists in Common Lisp

I have been playing with clojure for some time. There are some really nice utility functions that I got used to working with. The merge-with function is one of those. The implementation I posted below is almost trivial, but hey: I haven’t posted anything in a while and this certainly scratched my programming itch just enough.

Description of the Problem

Assume we have a collection of association lists and we would like to combine them carefully: for a pair (x . y) if the key x appeared before, then we are going to use a combination function fn on the current cdr of the (x . val)pair and set the val to (fn val y).

Implementation

(defun merge-with (fn &rest alists)
   (let ((res (car alists)))
      (dolist (current (reduce #'append (cdr alists)) res)
         (let ((val (cdr (assoc (car current) res :test #'equal))))
            (if (null val)
               (push current res)
               (rplacd (assoc (car current) res :test #'equal)
                       (funcall fn val (cdr current))))))))
MERGE-WITH

and we test:

(merge-with #'+ '(("a" . 1) ("b" . 2)) '(("c" . 2) ("a" . 13) ("b" . 13)) '(("a" . -8)))
((c . 2) (a . 6) (b . 15))