1
0
mirror of https://git.savannah.gnu.org/git/emacs.git synced 2025-01-14 16:50:58 +00:00

Further seq-uniq speed-ups for lists

* lisp/emacs-lisp/seq.el (seq-uniq): Speed up more for long lists
(bug#57079).
This commit is contained in:
Lars Ingebrigtsen 2022-08-12 15:15:11 +02:00
parent f947b20a19
commit c0d761bf7f
2 changed files with 21 additions and 6 deletions

View File

@ -458,11 +458,21 @@ TESTFN is used to compare elements, or `equal' if TESTFN is nil."
(cl-defmethod seq-uniq ((sequence list) &optional testfn)
(let ((result nil))
(if (not testfn)
;; Fast path.
(while sequence
(unless (member (car sequence) result)
(push (car sequence) result))
(pop sequence))
;; Fast path. If the list is long, use a hash table to speed
;; things up even more.
(let ((l (length sequence)))
(if (> l 100)
(let ((hash (make-hash-table :test #'equal :size l)))
(while sequence
(unless (gethash (car sequence) hash)
(setf (gethash (car sequence) hash) t)
(push (car sequence) result))
(setq sequence (cdr sequence))))
;; Short list.
(while sequence
(unless (member (car sequence) result)
(push (car sequence) result))
(pop sequence))))
;; Slower path.
(while sequence
(unless (seq-find (lambda (elem)

View File

@ -570,7 +570,12 @@ Evaluate BODY for each created sequence.
(substring "2")
(substring "1"))))
(should (equal (seq-uniq list) '("1" "2" "3")))
(should (equal (seq-uniq list #'eq) '("1" "2" "3" "2" "1")))))
(should (equal (seq-uniq list #'eq) '("1" "2" "3" "2" "1"))))
;; Long lists have a different code path.
(let ((list (seq-map-indexed (lambda (_ i) i)
(make-list 10000 nil))))
(should (= (length list) 10000))
(should (= (length (seq-uniq (append list list))) 10000))))
(provide 'seq-tests)
;;; seq-tests.el ends here