Hi there,
Prompted by a discussion on #lisp, I've made the following collect-duplicates function: Takes a sequence and a test, and returns as two values a sequence of duplicates and a sequence of the duplicate count (matching their sequence type to the input sequence's).
(defun collect-duplicates (sequence &key (test #'eql)) ;; This will work only for TESTs that are valid hash tests: (let ((dupes (make-hash-table :test test)) (known (make-hash-table :test test))) (map nil (lambda (elt) (if (gethash elt known) (incf (gethash elt dupes 1)) (setf (gethash elt known) t))) sequence) (let ((duplicates (make-sequence (class-of sequence) (hash-table-count dupes))) (counts (make-sequence (class-of sequence) (hash-table-count dupes))) (i 0)) (maphash (lambda (k v) (setf (elt duplicates i) k (elt counts i) v) (incf i)) dupes) (values duplicates counts))))
Issues that I see with it:
* Needs a :key argument. * :test should allow for non-hash-table tests, as well. * (class-of ...) is not really a good idea, as it doesn't preserve the element type for arrays.
If I fixed these issues, would there be interest in having this function in alexandria?
Cheers,