Usando traço:
(defun find-duplicates (list)
"Return a list that contains each element from LIST that occurs more than once."
(--> list
(-group-by #'identity it)
(-filter (lambda (ele) (> (length ele) 2)) it)
(mapcar #'car it)))
Um conjunto de testes rápidos:
(ert-deftest nothing ()
(should-not (find-duplicates '())))
(ert-deftest no-duplicates ()
(should-not (find-duplicates '(1 2 3 4 5 6 7 "eight"))))
(ert-deftest single-duplicate ()
(should (equal (find-duplicates '(1 2 3 4 1))
'(1))))
(ert-deftest multiple-duplicates ()
(should (equal (sort (find-duplicates '(1 2 3 4 1 6 7 8 9 2))
#'<)
'(1 2))))
(ert-deftest string-duplicates ()
(should (equal (find-duplicates '(1 2 "three" 4 "three"))
'("three"))))
Atualmente, parece retornar os itens na ordem da primeira ocorrência de cada duplicata, mas não vejo nada -group-by
que garanta isso; portanto, acho que não podemos confiar nisso. Poderia ser mais eficiente, usando hashtables, mas isso funciona.