8

I am using Intermediate Student with Lambda in DrRacket, I was wondering how one would remove the duplicates in a list, while keeping the order. For example (remove-dup (list 2 5 4 5 1 2)) would produce (list 2 5 4 1). So far, I have this:

(define (remove-duplicates lst)
  (cond
    [(empty? lst) empty]
    [(member? (first lst) (rest lst)) 
     (remove-duplicates (rest lst))]
    [else (cons (first lst) (remove-duplicates (rest lst)))]))

, but there's a problem since it doesn't keep the order. Can someone point me in the right direction? Thanks for your time.

ruakh
  • 175,680
  • 26
  • 273
  • 307
J-Y
  • 365
  • 3
  • 9
  • 18
  • 4
    Actually, it looks like it *does* preserve the order, just doesn't keep the first of the duplicated elements. Are you sure that your solution is incorrect? – John Clements Nov 16 '11 at 03:17
  • unfortunately the solution is incorrect. For example if I have remove-duplicates (1 2 5 1 4), I want (list 1 2 5 4), instead of the actual value of (list 2 5 1 4). Sorry for the bad example. – J-Y Nov 16 '11 at 14:52
  • I was thinking of doing something like cons the 1st of the list, and then use filter on the rest of the list with the 1st number. Except, I don't know how to implement that haha. – J-Y Nov 16 '11 at 14:56
  • I would look into using an accumulator here if you've learned about them (assuming this is for a class). – Asumu Takikawa Nov 16 '11 at 15:38
  • This problem does not require an accumulator; you can do it with a helper function. I would consider calling it 'remove'. The asymptotic complexity is the same. – John Clements Nov 17 '11 at 22:45

8 Answers8

13

If your goal is to get the functionality working, and not some homework question, then you don't need to do anything, just use remove-duplicates:

Welcome to Racket v5.2.
-> (remove-duplicates (list 2 5 4 5 1 2))
'(2 5 4 1)
Eli Barzilay
  • 29,301
  • 3
  • 67
  • 110
5

This is the solution:

(define (remove-duplicates lon)
  (foldr (lambda (x y) (cons x (filter (lambda (z) (not (= x z))) y))) empty lon))
Peter O.
  • 32,158
  • 14
  • 82
  • 96
Salem Talha
  • 51
  • 1
  • 1
1

Old question, but this is an implementation of J-Y's idea.

(define (dup-rem lst)
  (cond
    [(empty? lst) empty]
    [else (cons (first lst) (dup-rem (filter (lambda (x) (not (equal? (first lst) x))) lst)))]))
No_name
  • 2,732
  • 3
  • 32
  • 48
0

SRFI-1 has delete-duplicates, although it's inefficient. (I am not too familiar with Racket, but surely it has SRFI-1, and the source...)

http://srfi.schemers.org/srfi-1/srfi-1.html#delete-duplicates

Hans Nowak
  • 7,600
  • 1
  • 18
  • 18
  • I took a look at the website, but I believe the source code provided does not work in Racket. – J-Y Nov 16 '11 at 14:53
  • 2
    You can use `srfi/1` in Racket by just adding `(require srfi/1)` to your program. However, `remove-duplicates` as mentioned in the first answer is even easier to get -- it's there by default in Racket. – Sam Tobin-Hochstadt Nov 20 '11 at 15:44
0

Run through the list sequentially, inserting each element in a hash table or other dictionary. If you try to insert an element that is already in the hash table, do not add it to the outgoing list.

user448810
  • 17,381
  • 4
  • 34
  • 59
0

What you need to do is compare in reverse order the entire time. You can use the reverse function which returns a list in reverse order. That way you are always removing the 2nd+ occurrence of an element and not the first. Here is an example, however it is using let and if and not a cond expression.

http://www.cs.bgu.ac.il/~elhadad/scheme/duplicates.html

Good luck with your homework :)

danielrsmith
  • 4,050
  • 3
  • 26
  • 32
0

I'm not sure if this is homework, but in case it is I'll post just the idea. If it's not tell me and I can put a solution here.

What you need is to keep track of the unique items you find, you can do that by using an auxiliary list, like an accumulator, to keep track of the ones you found so far.

Whenever you look at another item check to see if it's in the auxiliary list. In case it's not add it to the auxiliary list.

You'll end up with a reverse order of what you're trying to find, so you can just (reverse ...) it and you'll have your answer.

Kara
  • 6,115
  • 16
  • 50
  • 57
  • You'd better prefer a hash set to a list to keep the items you've seen. With a list, the function is `Theta (n^2)` . With a hash-set, it's `Theta (n)`. – Thumbnail May 26 '17 at 19:21
0

hmm i just had a racket exam recently, :/

the 'standard' remove-duplicates works fine but i was using pretty-big in drRacket so it had to be loaded using (require racket/list)

here is an alternative way :)

using mutation (not really in the spirit of racket but.. it works.)

    (define (set l)
        (define the-set '())
            (begin (for-each
                       (lambda (x)
                            (if (member x the-set)
                                #t
                            (set! the-set (cons x the-set))))
                       l)
                   (reverse the-set)))

hope this helps... cheers!

michael
  • 51
  • 1
  • 4