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