问题
I know how to write this in an recursive way.
(define (removed2 lst)
(cond
[(empty? lst) empty]
[(not (member? (first lst) (rest lst)))
(cons (first lst) (removed2 (rest lst)))]
[else (removed2 (rest lst))]))
so (removed2 (list 1 1 1 2 2 2 3 3 3 3 3 3)) gives (list 1 2 3)
However, how do you rewrite it only using abstract functions (filter, foldr, map, and build-list)?
I tried to use filter but it just doesn't work.
回答1:
It's possible to use foldr
for this, the trick is knowing what to write in the lambda
:
(define (removed lst)
(foldr (lambda (e a)
(if (not (member? e a))
(cons e a)
a))
'()
lst))
Also check if your interpreter has a built-in function, for instance in Racket you can use remove-duplicates
.
回答2:
FILTER
Just for kicks, a version with filter
:
(define (make-unique-filter)
(let ((seen '()))
(lambda (e)
(if (member e seen)
#f
(begin
(set! seen (cons e seen))
#t)))))
(define (removed2 lst)
(filter (make-unique-filter) lst))
then
(removed2 (list 1 1 1 2 2 2 3 3 3 3 3 3))
=> '(1 2 3)
(removed2 (list 1 2 3 1 2 3 1 2 3 1 2 3))
=> '(1 2 3)
FOLD
But of course, fold is the way to go. However, it is generally preferable to user a left fold (at least in Racket, see here), but the result has to be reversed:
(define (removed2 lst)
(reverse
(foldl
(lambda (e a)
(if (not (member e a))
(cons e a)
a))
'()
lst)))
or in pure Scheme:
(define (removed2 lst)
(reverse
(fold-left
(lambda (a e)
(if (not (member e a))
(cons e a)
a))
'()
lst)))
来源:https://stackoverflow.com/questions/21298989/how-to-remove-all-the-duplicates-in-a-list-using-scheme-only-abstract-list-func