Existe uma função como `assoc` que retorna todos os valores correspondentes?

7

A assoc KEY LISTfunção retorna o primeiro elemento de um alistcujo carro é igual a KEY.

Existe uma função interna do Emacs Lisp que retorna todos os elementos de alistcujos carros são iguais a KEY, como um subalista ou lista de valores? Afinal, não é necessário que um alisttenha chaves exclusivas.

Isso é,

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

Mas,

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

Respostas:

6

Algo assim?

(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
fonte
11
Por favor, nomes de função prefixo com #'em vez de apenas 'para dizer ao compilador esta é uma referência de função (obras para ambos 'equale 'car) ..
Damien Cassou
Feito; embora, que eu saiba, isso seja totalmente redundante nesse caso - só afetaria algo se carou equalnão fosse definido, não?
Phill
De acordo com sua definição, #'é sempre redundante, pois você deve referenciar apenas funções definidas :-). Eu acho que é um bom hábito sempre citar suas referências de função. E, quem sabe, o compilador de bytes poderá um dia usar essas informações para otimizar seu código :-).
Damien Cassou
5

Outra solução envolvendo seq-filter:

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