我正在尝试使用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 '()))
我用“奇怪的”做了几个测试,“甚至?”和“数字?”作为“检查功能”。
所有输出都是正确的。但我可能没有看到一些东西......我的直觉说这里有问题。
答案 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)