]> git.eshelyaron.com Git - emacs.git/commitdiff
Add a faster seq-uniq for lists
authorLars Ingebrigtsen <larsi@gnus.org>
Tue, 9 Aug 2022 17:18:55 +0000 (19:18 +0200)
committerLars Ingebrigtsen <larsi@gnus.org>
Tue, 9 Aug 2022 17:21:36 +0000 (19:21 +0200)
* lisp/emacs-lisp/seq.el (seq-uniq): Add a faster method for lists
(bug#57079).

lisp/emacs-lisp/seq.el
test/lisp/emacs-lisp/seq-tests.el

index 1b8d86563a1ac28093eadd14010217402e90029c..6ddd8de6e8d2a49b008328ca4968196bde0ba8f0 100644 (file)
@@ -455,6 +455,23 @@ TESTFN is used to compare elements, or `equal' if TESTFN is nil."
         (setq result (cons elt result))))
     (nreverse result)))
 
+(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))
+      ;; Slower path.
+      (while sequence
+        (unless (seq-find (lambda (elem)
+                            (funcall testfn elem (car sequence)))
+                          result)
+          (push (car sequence) result))
+        (pop sequence)))
+    (nreverse result)))
+
 (cl-defgeneric seq-mapcat (function sequence &optional type)
   "Concatenate the result of applying FUNCTION to each element of SEQUENCE.
 The result is a sequence of type TYPE, or a list if TYPE is nil."
index 3b22e42df2426c757f5e957e24e258631ef41604..a655377e6ccb72a6bd820e26c2c70070c6c4762b 100644 (file)
@@ -559,5 +559,18 @@ Evaluate BODY for each created sequence.
     (should (equal (seq-split seq 3)
                    '("012" "345" "678" "9")))))
 
+(ert-deftest test-seq-uniq-list ()
+  (let ((list '(1 2 3)))
+    (should (equal (seq-uniq (append list list)) '(1 2 3))))
+  (let ((list '(1 2 3 2 1)))
+    (should (equal (seq-uniq list) '(1 2 3))))
+  (let ((list (list (substring "1")
+                    (substring "2")
+                    (substring "3")
+                    (substring "2")
+                    (substring "1"))))
+    (should (equal (seq-uniq list) '("1" "2" "3")))
+    (should (equal (seq-uniq list #'eq) '("1" "2" "3" "2" "1")))))
+
 (provide 'seq-tests)
 ;;; seq-tests.el ends here