7

The assoc KEY LIST function returns the first element of an alist whose car is equal to KEY.

Is there a built-in Emacs Lisp function which returns all elements of the alist whose cars are equal to KEY, as a sub-alist, or list of values? After all, there is no requirement that an alist have unique keys.

That is,

(assoc foo '((foo . 5) (bar . 6) (foo . 7))) = '(foo . 5)

But,

(assoc-all foo '((foo . 5) (bar . 6) (foo . 7))) = '((foo . 5) (foo . 7))
6

Something like this?

(require 'cl-lib)

(cl-remove-if-not (apply-partially #'equal 'foo)
                  '((foo . 5) (bar . 6) (foo . 7))
                  :key #'car)

=> ((foo . 5) (foo . 7))
(defun assoc-all (key list &optional testfn)
  "Like `assoc', but returns the list of all matching elements."
  (cl-remove-if-not (apply-partially (or testfn #'equal) key)
                    list :key #'car))
  • 1
    Please prefix function names with #' instead of just ' to tell the compiler this is a function reference (works for both 'equal and 'car).. – Damien Cassou May 23 '18 at 9:28
  • Done; although to my knowledge this is entirely redundant in this instance -- it would only affect anything if car or equal might not be defined, no? – phils May 23 '18 at 15:48
  • According to your definition, #' is always redundant as you are supposed to only reference defined functions :-). I think it's a good habit to always sharp-quote your function references. And, who knows, the byte compiler might one day use this information to optimize your code :-). – Damien Cassou May 24 '18 at 14:43
5

Another solution involving seq-filter:

(seq-filter (lambda (elt) (equal (car elt) 'foo))
            '((foo . 5) (bar . 6) (foo . 7)))

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.