Remove duplicates from list

Problem

You have a list and you want to remove any duplicated elements from the list and the order should not change. The solution can use the equal? procedure or use the comparison procedure as an argument.

Solution

Using SRFI

There's a delete-duplicates procedure in SRFI 1.

Using hash tables (SRFI 125)

(define (delete-duplicates xs)
  (let ((seen (make-hash-table equal?)))
    (let loop ((xs xs) (new-list '()))
      (if (null? xs)
          (reverse new-list)
          (loop (cdr xs)
                (let ((x (car xs)))
                  (if (hash-table-contains? seen x)
                      new-list
                      (begin (hash-table-set! seen x #t)
                             (cons x new-list)))))))))

Credit: Lassi Kortela

Removing only adjacent duplicates

Here's a version that removes only duplicates that are adjacent (i.e. next to each other). It doesn't need to use a hash table or other memory.

(define (delete-adjacent-duplicates xs)
  (let loop ((prev-pair #f) (xs xs) (new-list '()))
    (if (null? xs)
        (reverse new-list)
        (loop xs
              (cdr xs)
              (let ((x (car xs)))
                (if (and prev-pair (equal? x (car prev-pair)))
                    new-list
                    (cons x new-list)))))))

Credit: Lassi Kortela

Usage

(define numbers '(1 2 3 1 2 4 4 5 6 7 5))

(delete-duplicates numbers)
;; ==> (1 2 3 4 5 6 7)

(delete-adjacent-duplicates numbers)
;; ==> (1 2 3 1 2 4 5 6 7 5)

Back to the Scheme Cookbook