Commit c0d761bf authored by Lars Ingebrigtsen's avatar Lars Ingebrigtsen
Browse files

Further seq-uniq speed-ups for lists

* lisp/emacs-lisp/seq.el (seq-uniq): Speed up more for long lists
parent f947b20a
Pipeline #19887 passed with stages
in 41 minutes and 45 seconds
......@@ -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)
......@@ -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
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment