Unique & Duplicate List Functions
Here are various subfunctions for manipulating lists in which items appear more than once. The list may be tested for or irradicated of all duplicate items, with a set of functions offering optional tolerances below which items are considered duplicate; or such duplicate items may instead be returned by the function. Alternatively, the number of occurrences of each item in a list may be displayed.
Information about the purpose of each function is detailed in the comments above each function, and the required arguments and returns are demonstrated in the examples.
Contents
Unique
Recursive
;; Unique - Lee Mac ;; Returns a list with duplicate elements removed. (defun LM:Unique ( l ) (if l (cons (car l) (LM:Unique (vl-remove (car l) (cdr l))))) )
Iterative
;; Unique - Lee Mac ;; Returns a list with duplicate elements removed. (defun LM:Unique ( l / x r ) (while l (setq x (car l) l (vl-remove x (cdr l)) r (cons x r) ) ) (reverse r) )
Example
(LM:Unique '("A" "B" "B" "B" "C" "C" "D" "E" "E" "E" "E")) => ("A" "B" "C" "D" "E") (LM:Unique '(1 2 3 3 3 4 5 6 6 7 8 8 8 8)) => (1 2 3 4 5 6 7 8)
Unique-p
Recursive
;; Unique-p - Lee Mac ;; Returns T if the supplied list contains distinct items. (defun LM:Unique-p ( l ) (or (null l) (and (not (member (car l) (cdr l))) (LM:Unique-p (cdr l)) ) ) )
Iterative
;; Unique-p - Lee Mac ;; Returns T if the supplied list contains distinct items. (defun LM:Unique-p ( l ) (vl-every (function (lambda ( x ) (not (member x (setq l (cdr l)))))) l) )
Example
_$ (LM:Unique-p '(1 2 3 4 5)) T _$ (LM:Unique-p '(1 2 3 3 3 4 5)) nil
Unique with Fuzz
Recursive
;; Unique with Fuzz - Lee Mac ;; Returns a list with all elements considered duplicate to ;; a given tolerance removed. (defun LM:UniqueFuzz ( l f ) (if l (cons (car l) (LM:UniqueFuzz (vl-remove-if (function (lambda ( x ) (equal x (car l) f))) (cdr l) ) f ) ) ) )
Iterative
;; Unique with Fuzz - Lee Mac ;; Returns a list with all elements considered duplicate to ;; a given tolerance removed. (defun LM:UniqueFuzz ( l f / x r ) (while l (setq x (car l) l (vl-remove-if (function (lambda ( y ) (equal x y f))) (cdr l)) r (cons x r) ) ) (reverse r) )
Example
_$ (LM:UniqueFuzz '(1.0 1.1 2.0 2.01 2.2) 0.01) (1.0 1.1 2.0 2.2) _$ (LM:UniqueFuzz '(1.0 1.1 2.0 2.01 2.2) 0.15) (1.0 2.0 2.2)
Unique-p with Fuzz
Recursive
;; Unique-p with Fuzz - Lee Mac ;; Returns T if a list contains items considered distinct to ;; a given tolerance (defun LM:UniqueFuzz-p ( l f ) (or (null l) (and (not (vl-some (function (lambda ( x ) (equal x (car l) f))) (cdr l))) (LM:UniqueFuzz-p (cdr l) f) ) ) )
Iterative
;; Unique-p with Fuzz - Lee Mac ;; Returns T if a list contains items considered distinct to ;; a given tolerance (defun LM:UniqueFuzz-p ( l f ) (vl-every (function (lambda ( x ) (not (vl-some (function (lambda ( y ) (equal x y f)) ) (setq l (cdr l)) ) ) ) ) l ) )
Example
_$ (LM:UniqueFuzz-p '(1.0 1.1 2.0 2.01 2.2) 0.01) nil _$ (LM:UniqueFuzz-p '(1.0 1.1 2.0 2.01 2.2) 0.001) T
List Duplicates
Recursive
;; List Duplicates - Lee Mac ;; Returns a list of items appearing more than once in a supplied list (defun LM:ListDupes ( l ) (if l (if (member (car l) (cdr l)) (cons (car l) (LM:ListDupes (vl-remove (car l) (cdr l)))) (LM:ListDupes (vl-remove (car l) (cdr l))) ) ) )
Iterative
;; List Duplicates - Lee Mac ;; Returns a list of items appearing more than once in a supplied list (defun LM:ListDupes ( l / x r ) (while l (if (member (setq x (car l)) (cdr l)) (setq r (cons x r)) ) (setq l (vl-remove x (cdr l))) ) (reverse r) )
Example
(LM:ListDupes '("A" "B" "B" "B" "C" "C" "D" "E" "E" "E" "E")) => ("B" "C" "E") (LM:ListDupes '(1 2 3 3 3 4 5 6 6 7 8 8 8 8)) => (3 6 8)
Count Items
Recursive
;; Count Items - Lee Mac ;; Returns a list of dotted pairs detailing the number of ;; occurrences of each item in a supplied list. (defun LM:CountItems ( l / c x ) (if (setq x (car l)) (progn (setq c (length l) l (vl-remove x (cdr l)) ) (cons (cons x (- c (length l))) (LM:CountItems l)) ) ) )
Iterative
;; Count Items - Lee Mac ;; Returns a list of dotted pairs detailing the number of ;; occurrences of each item in a supplied list. (defun LM:CountItems ( l / c l r x ) (while l (setq x (car l) c (length l) l (vl-remove x (cdr l)) r (cons (cons x (- c (length l))) r) ) ) (reverse r) )
Example
(LM:CountItems '("A" "B" "B" "B" "C" "C" "D" "E" "E" "E" "E")) => (("A" . 1) ("B" . 3) ("C" . 2) ("D" . 1) ("E" . 4)) (LM:CountItems '(1 2 3 3 3 4 5 6 6 7 8 8 8 8)) => ((1 . 1) (2 . 1) (3 . 3) (4 . 1) (5 . 1) (6 . 2) (7 . 1) (8 . 4))