diff --git a/lisp/emacs-lisp/map.el b/lisp/emacs-lisp/map.el index 77431f0c59..9db2ddd95f 100644 --- a/lisp/emacs-lisp/map.el +++ b/lisp/emacs-lisp/map.el @@ -202,6 +202,25 @@ map-nested-elt map) default)) +(defun map--remove-duplicate-keys (map) + "Make a version of MAP without duplicated keys. + +Unlike hash tables, association and property lists allow +duplicate keys in the data structure. This function returns the +map with such keys and their respective data removed." + (if (map--plist-p map) + (let ((found-keys) + (result)) + (while map + (let ((key (pop map)) + (value (pop map))) + (unless (member key found-keys) + (push key found-keys) + (push key result) + (push value result)))) + (nreverse result)) + (seq-uniq map (lambda (a b) (equal (car a) (car b)))))) + (cl-defgeneric map-keys (map) "Return the list of keys in MAP. The default implementation delegates to `map-apply'." @@ -234,6 +253,7 @@ map-length (hash-table-count map)) (cl-defmethod map-length ((map list)) + (setq map (map--remove-duplicate-keys map)) (if (map--plist-p map) (/ (length map) 2) (length map))) @@ -489,7 +509,7 @@ map-apply (cl-call-next-method) (mapcar (lambda (pair) (funcall function (car pair) (cdr pair))) - map))) + (map--remove-duplicate-keys map)))) (cl-defmethod map-apply (function (map hash-table)) (let (result) @@ -504,6 +524,7 @@ map-apply map)) (cl-defmethod map-do (function (map list)) + (setq map (map--remove-duplicate-keys map)) (if (map--plist-p map) (while map (funcall function (pop map) (pop map)))