重复过滤后列出顺序

时间:2014-02-25 00:09:45

标签: scheme racket

我正在尝试自学功能语言思维并编写了一个过程,该过程采用列表并返回一个过滤掉重复项的列表。这是有效的,但输出列表按输入列表中找到每个重复项的 last 实例的顺序排序。

(define (inlist L n)
  (cond
   ((null? L) #f)
   ((= (car L) n) #t)
   (else (inlist (cdr L) n))
   ))

(define (uniquelist L)
 (cond
   ((null? L) '())
   ((= 1 (length L)) L)
   ((inlist (cdr L) (car L)) (uniquelist (cdr L)))
   (else (cons (car L) (uniquelist (cdr L))))
   ))

所以..

(uniquelist '(1 1 2 3)) => (1 2 3)

...但是...

(uniquelist '(1 2 3 1)) => (2 3 1)

是否有一个简单的替代方案可以维护每个副本的第一个实例的顺序?

1 个答案:

答案 0 :(得分:2)

解决此问题的最佳方法是使用Racket的内置remove-duplicates程序。但是,当然,您希望从头开始实施该解决方案。以下是使用惯用Racket的方法,请注意我们可以使用member(另一个内置函数)代替inlist

(define (uniquelist L)
  (let loop ([lst (reverse L)] [acc empty])
    (cond [(empty? lst)
           acc]
          [(member (first lst) (rest lst))
           (loop (rest lst) acc)]
          [else
           (loop (rest lst) (cons (first lst) acc))])))

或者我们可以使用标准Scheme编写相同的过程,如SICP所示:

(define (uniquelist L)
  (let loop ((lst (reverse L)) (acc '()))
    (cond ((null? lst)
           acc)
          ((member (car lst) (cdr lst))
           (loop (cdr lst) acc))
          (else
           (loop (cdr lst) (cons (car lst) acc))))))

以上内容使用named let进行迭代,并展示了如何编写tail-recursive实现。它按预期工作:

(uniquelist '(1 1 2 3))
=> '(1 2 3)

(uniquelist '(1 2 3 1))
=> '(1 2 3)