filter - 使用 Racket 构建过滤器内置函数

标签 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 '()))

我用“奇数?”、“偶数?”做了一些测试。和“数字?”作为“检查功能”。

所有输出都是正确的。但我可能没有看到什么……我的直觉告诉我这里有问题。

最佳答案

你的函数是正确的,只是它的复杂度为 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 '()))

关于filter - 使用 Racket 构建过滤器内置函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40118526/

相关文章:

xml - haskell:xml过滤子树

algorithm - Lisp:如何从列表中包含的列表中获取元素的所有可能组合?

emacs - 在 emacs 中最大化/恢复窗口

lisp - 有没有办法在 Common-Lisp 中不传递参数而不是传递 "NIL"?

ios - 在 iOS 中使用谓词过滤数组

c++ - 传递给 IMediaFilter::Run 的偏移参数

filter - 表格 : Create global filter from a secondary data source to multiple data sources on dashboard

java stream groupingBy嵌入对象

c# - 仿函数和 "generics"有什么区别

scala - 不同函数式编程概念之间的关系