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,
--
Andreas Fuchs, (http://|im:asf@|mailto:asf@)boinkor.net, antifuchs