¿Existe una función como `assoc` que devuelve todos los valores coincidentes?

7

La assoc KEY LISTfunción devuelve el primer elemento de un alistautomóvil cuyo es igual a KEY.

¿Existe una función incorporada de Emacs Lisp que devuelve todos los elementos de alistcuyos automóviles son iguales KEY, como una sublista o una lista de valores? Después de todo, no es necesario que alisttenga claves únicas.

Es decir,

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

Pero,

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

Respuestas:

6

¿Algo como esto?

(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))
phils
fuente
1
Por favor, prefije los nombres de las funciones en #'lugar de solo 'decirle al compilador que esta es una referencia de función (funciona para ambos 'equaly 'car) ..
Damien Cassou
Hecho; aunque, que yo sepa, esto es completamente redundante en este caso, solo afectaría cualquier cosa si se definiera caro equalno, ¿no?
Phil
Según su definición, #'siempre es redundante ya que se supone que solo debe hacer referencia a funciones definidas :-). Creo que es una buena costumbre citar siempre las referencias de sus funciones. Y, quién sabe, el compilador de bytes podría algún día utilizar esta información para optimizar su código :-).
Damien Cassou
5

Otra solución que involucra seq-filter:

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