]> code.delx.au - gnu-emacs/commitdiff
* lisp/emacs-lisp/map.el (map-merge-with): New function
authorArtur Malabarba <bruce.connor.am@gmail.com>
Sat, 7 Nov 2015 12:45:18 +0000 (12:45 +0000)
committerArtur Malabarba <bruce.connor.am@gmail.com>
Tue, 10 Nov 2015 13:04:30 +0000 (13:04 +0000)
* test/automated/map-tests.el (test-map-merge-with): New test

lisp/emacs-lisp/map.el
test/automated/map-tests.el

index 5ef51f12d960d59772bc2fa3c5784acb721fb20c..7ff9031b08d978422ccf64c7c97b2d32335de429 100644 (file)
@@ -279,9 +279,9 @@ MAP can be a list, hash-table or array."
 MAP can be a list, hash-table or array."
   (catch 'map--break
     (map-apply (lambda (key value)
-                 (or (funcall pred key value)
-                     (throw 'map--break nil)))
-               map)
+              (or (funcall pred key value)
+                  (throw 'map--break nil)))
+            map)
     t))
 
 (defun map-merge (type &rest maps)
@@ -291,8 +291,23 @@ MAP can be a list, hash-table or array."
   (let (result)
     (while maps
       (map-apply (lambda (key value)
-                   (setf (map-elt result key) value))
-                 (pop maps)))
+                (setf (map-elt result key) value))
+              (pop maps)))
+    (map-into result type)))
+
+(defun map-merge-with (type function &rest maps)
+  "Merge into a map of type TYPE all the key/value pairs in MAPS.
+When two maps contain the same key, call FUNCTION on the two
+values and use the value returned by it.
+MAP can be a list, hash-table or array."
+  (let (result)
+    (while maps
+      (map-apply (lambda (key value)
+                (setf (map-elt result key)
+                      (if (map-contains-key result key)
+                          (funcall function (map-elt result key) value)
+                        value)))
+              (pop maps)))
     (map-into result type)))
 
 (defun map-into (map type)
index 8693415a784cbae66414a9f1fca8285dbfb360e7..1a759b523a512a4d25e54b1b41794d3e8619ec80 100644 (file)
@@ -320,5 +320,12 @@ Evaluate BODY for each created map.
     (should (= b 2))
     (should (null c))))
 
+(ert-deftest test-map-merge-with ()
+  (should (equal (map-merge-with 'list #'+
+                                 '((1 . 2))
+                                 '((1 . 3) (2 . 4))
+                                 '((1 . 1) (2 . 5) (3 . 0)))
+                 '((3 . 0) (2 . 9) (1 . 6)))))
+
 (provide 'map-tests)
 ;;; map-tests.el ends here