如何使用scheme删除列表中的所有重复项(仅允许抽象列表函数)

时间:2014-01-23 03:50:52

标签: scheme

我知道如何以递归方式编写它。

(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))给出(list 1 2 3)

但是,如何仅使用抽象函数(filter,foldr,map和build-list)重写它?

我尝试使用过滤器,但它不起作用。

2 个答案:

答案 0 :(得分:2)

为此可以使用foldr,诀窍是知道在lambda中写什么:

(define (removed lst)
  (foldr (lambda (e a)
           (if (not (member? e a))
               (cons e a)
               a))
         '()
         lst))

同时检查您的口译员是否具有内置功能,例如在Racket中您可以使用remove-duplicates

答案 1 :(得分:2)

过滤

仅限于踢,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))

然后

(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

但当然, fold 是要走的路。但是,通常最好使用左侧折叠(至少在Racket中,请参阅here),但结果必须颠倒过来:

(define (removed2 lst)
  (reverse 
   (foldl 
    (lambda (e a)
      (if (not (member e a))
          (cons e a)
          a))
    '()
    lst)))

或纯粹的方案:

(define (removed2 lst)
  (reverse 
   (fold-left 
    (lambda (a e)
      (if (not (member e a))
          (cons e a)
          a))
    '()
    lst)))