remove-duplicates: use hash-tables for :test #'=

This commit is contained in:
Stas Boukarev 2026-03-18 18:19:42 +03:00
parent c7aa6982c6
commit 0e4ad432dd
3 changed files with 15 additions and 2 deletions

View file

@ -2549,7 +2549,9 @@ many elements are copied."
((eq fun #'string=) ((eq fun #'string=)
(make-hash-table :test #'string= :hash-function #'string=-hash :size size)) (make-hash-table :test #'string= :hash-function #'string=-hash :size size))
((eq fun #'string-equal) ((eq fun #'string-equal)
(make-hash-table :test #'string-equal :hash-function #'string-equal-hash :size size)))) (make-hash-table :test #'string-equal :hash-function #'string-equal-hash :size size))
((eq fun #'=)
(make-hash-table :test #'= :hash-function #'psxhash :size size))))
;;; Remove duplicates from a list. If from-end, remove the later duplicates, ;;; Remove duplicates from a list. If from-end, remove the later duplicates,
;;; not the earlier ones. Thus if we check from-end we don't copy an item ;;; not the earlier ones. Thus if we check from-end we don't copy an item

View file

@ -477,6 +477,7 @@
(unwind-protect (unwind-protect
(let ((transformed-cases '((integer sb-impl::integer-sxhash) (let ((transformed-cases '((integer sb-impl::integer-sxhash)
(number sb-impl::number-sxhash) (number sb-impl::number-sxhash)
#-sb-devel ;; where sb-impl::instance-sxhash is inlined
(sb-kernel:instance sb-impl::instance-sxhash))) (sb-kernel:instance sb-impl::instance-sxhash)))
(inlined-cases '(single-float double-float fixnum))) (inlined-cases '(single-float double-float fixnum)))
(loop for (type . hasher) in transformed-cases (loop for (type . hasher) in transformed-cases

View file

@ -76,7 +76,7 @@
(assert (equalp (remove-duplicates orig :start 3 :end 9) '(0 1 2 0 1 2 0 1 2))) (assert (equalp (remove-duplicates orig :start 3 :end 9) '(0 1 2 0 1 2 0 1 2)))
(assert (equalp (delete-duplicates orig :start 3 :end 9) '(0 1 2 0 1 2 0 1 2))))) (assert (equalp (delete-duplicates orig :start 3 :end 9) '(0 1 2 0 1 2 0 1 2)))))
(with-test (:name (remove-duplicates delete-duplicates :key)) (with-test (:name (remove-duplicates :key))
(let* ((negative (loop :for i :from 1 :to 11 :collect (- i))) (let* ((negative (loop :for i :from 1 :to 11 :collect (- i)))
(positive (loop :for i :from 1 :to 11 :collect i)) (positive (loop :for i :from 1 :to 11 :collect i))
(combined (append negative positive)) (combined (append negative positive))
@ -86,6 +86,16 @@
(assert (equalp (coerce positive 'vector) (remove-duplicates vector :key #'abs))) (assert (equalp (coerce positive 'vector) (remove-duplicates vector :key #'abs)))
(assert (equalp (coerce negative 'vector) (remove-duplicates vector :key #'abs :from-end t))))) (assert (equalp (coerce negative 'vector) (remove-duplicates vector :key #'abs :from-end t)))))
(with-test (:name :remove-duplicates-test-=)
(let* ((negative (loop :for i :from 1 :to 11 :collect (- i)))
(positive (loop :for i :from 1 :to 11 :collect (float i)))
(combined (append negative positive))
(vector (coerce combined 'vector)))
(assert (equal positive (remove-duplicates combined :key #'abs :test #'=)))
(assert (equal negative (remove-duplicates combined :key #'abs :from-end t :test #'=)))
(assert (equalp (coerce positive 'vector) (remove-duplicates vector :key #'abs :test #'=)))
(assert (equalp (coerce negative 'vector) (remove-duplicates vector :key #'abs :from-end t :test #'=)))))
;;; tests of COUNT ;;; tests of COUNT
(with-test (:name (count)) (with-test (:name (count))
(assert (= 1 (count 1 '(1 2 3)))) (assert (= 1 (count 1 '(1 2 3))))