使用Racket构建过滤器内置功能

时间:2016-10-18 21:37:31

标签: filter functional-programming lisp racket sicp

我正在尝试使用Racket构建过滤器(内置函数),这只是一种练习。

我创建了以下代码:

(define (filter lista-1 check-function)
 (define (fil-iter lista-1 check-function lista-2)
  (cond ((null? lista-1) lista-2)
        ((check-function (car lista-1)) (fil-iter (cdr lista-1) check-function (append lista-2 (list (car lista-1)))))
        (else (fil-iter (cdr lista-1) check-function lista-2))))
   (trace fil-iter)
   (fil-iter lista-1 check-function '()))

我用“奇怪的”做了几个测试,“甚至?”和“数字?”作为“检查功能”。

所有输出都是正确的。但我可能没有看到一些东西......我的直觉说这里有问题。

2 个答案:

答案 0 :(得分:0)

你的功能是正确的,只有它的复杂性 n ²,而它的复杂性可能 n

原因是您使用append代替cons来构建结果,而append的成本与列表的长度成正比,而cons具有不变的成本。所以,如果你想要一个具有线性复杂度的函数,你应该写一些类似的东西:

(define (filter lista-1 check-function)
 (define (fil-iter lista-1 check-function lista-2)
  (cond ((null? lista-1) (reverse lista-2))
        ((check-function (car lista-1))
         (fil-iter (cdr lista-1) check-function (cons (car lista-1) lista-2)))
        (else (fil-iter (cdr lista-1) check-function lista-2))))
   (fil-iter lista-1 check-function '()))

请注意,最后必须反转结果,但这不会改变函数的复杂性,因为reverse具有列表大小的线性复杂性,并且只执行一次,在结尾处功能。

您还可以简化函数,注意在每次调用帮助器check-function时都不会修改参数fil-iter,因此可以在其中省略它:

(define (filter lista-1 check-function)
 (define (fil-iter lista-1 lista-2)
  (cond ((null? lista-1) (reverse lista-2))
        ((check-function (car lista-1))
         (fil-iter (cdr lista-1) (cons (car lista-1) lista-2)))
        (else (fil-iter (cdr lista-1) lista-2))))
   (fil-iter lista-1 '()))

答案 1 :(得分:0)

可以使用for/list#:when子句创建过滤函数:

(define (myfilter proc lst)
  (for/list ((item lst)
             #:when (proc item))
    item))

(myfilter even? '(1 2 3 4 5 6))
; => '(2 4 6)