目前正在尝试编写一个过滤函数,它接受一个过程列表和一个数字列表,删除在数字列表的每个元素上都不返回true的过程。
我所做的是以下内容,目前正在执行单个过程并在列表中运行以创建一个列表,说明每个元素的过程是真还是假。
使用foldr或map(如果需要)(非递归)
(define (my-filter ps xs)
(foldr (λ (x y)
(cons (ps x) y)) '() xs))
如果程序至少有一个#f?
,如何删除该程序即。 目前
> (my-filter even? '(1 2 3 4))
(#f #t #f #t)
> (my-filter even? (2 4))
(#t #t)
想
> (my-filter (list even?) '(1 2 3 4))
(list)
> (my-filter (list even?) '(2 4))
(list even?)
答案 0 :(得分:2)
您可以使用Racket的内置andmap
过程来解决此问题,该过程会测试列表中所有元素的条件是否为真 - 如下所示:
(define (my-filter ps xs)
(foldr (lambda (f acc)
(if (andmap f xs) ; if `f` is true for all elements in `xs`
(cons f acc) ; then add `f` to the accumulated output
acc)) ; otherwise leave the accumulator alone
'() ; initially the accumulator is an empty list
ps)) ; iterate over the list of functions
请注意,我们没有"删除"输出列表中的函数,而不是在每一步我们决定是否应该将它们添加到输出列表。
foldr
的优点是它保留了与输入列表相同的顺序,如果这不是一个要求,foldl
更有效,因为它在内部使用尾递归。无论哪种方式,它都按预期工作:
(my-filter (list even?) '(1 2 3 4))
=> '()
(my-filter (list even?) '(2 4))
=> '(#<procedure:even?>)
答案 1 :(得分:1)
从一些一厢情愿的想法开始。假设我们知道所有xs
是否对任何给定的#t
都返回f
(define (my-filter fs xs)
(foldr (λ (f y)
(if (every? f xs)
(cons f y)
y))
'()
fs))
现在让我们定义every?
(define (every? f xs)
(cond [(null? xs) #t]
[(f (car xs)) (every? f (cdr xs))]
[else #f]))
让我们查看(list even?)
(my-filter (list even?) '(1 2 3 4)) ; ⇒ '()
(my-filter (list even?) '(2 4)) ; ⇒ '(#<procedure:even?>)
让我们在混音中添加另一个测试
(define (gt3? x) (> x 3))
(my-filter (list even? gt3?) '(2 4)) ; ⇒ '(#<procedure:even?>)
(my-filter (list even? gt3?) '(4 6)) ; ⇒ '(#<procedure:even?> #<procedure:gt3?>)
酷!
如果你想看到&#34;漂亮&#34;过程名称而不是#<procedure:...>
内容,您可以将object-name
映射到结果数组
(map object-name (my-filter (list even? gt3?) '(4 6))) ; ⇒ '(even? gt3?)
即使
foldl
会给你一个反向输出,我仍然认为在这种情况下使用foldl
会更好。我的2美分。