Racket 函数用于查找列表中与谓词匹配的第一个元素
Racket function to find the first element in a list that matches a predicate
在 Linq (.NET) 中,有一个 First()
方法接受一个集合和一个谓词,returns 匹配列表中的第一个元素。例如,以下...
numbers.First(n => n % 2 == 0)
...returns numbers
中的第一个偶数。我想在 Racket 中做同样的事情。
我想到了以下...
(define (first-match f lst)
(first (filter f lst)))
...但我怀疑这可能非常低效,因为我认为它会在应用 first
之前过滤 整个 列表。 Linq 版本检查每个元素,因此只会遍历列表,直到找到匹配的元素。
任何人都可以证实或反驳我的假设,即我的 first-match
函数将遍历整个列表,如果是,我如何才能生成 Linq 的 First()
方法的更高效版本?
我尝试了以下版本的代码...
(define (first-match f lst)
(cond [(empty? lst) #f]
[(f (first lst)) (first lst)]
[else (first-match f (rest lst))]))
...只会遍历所需的距离,所以应该更有效率,但是
根据一些测试,这并没有快多少,这让我相信第一个版本没有遍历整个列表,或者第二个是。
有人可以发表评论吗?
谢谢
您的假设是正确的,即 (filter f lst)
在将结果传递给 first
之前将遍历整个输入列表(并在此基础上创建一个新列表!)。你的第二个版本效率更高,只会遍历列表直到找到元素。
但是在 Racket 中有一个更简单的解决方案,有一个内置程序可以完全你想要的:看findf
!
(findf even? '(1 3 5 2 4))
=> 2
(findf even? '(1 3 5 7 9))
=> #f
在 Linq (.NET) 中,有一个 First()
方法接受一个集合和一个谓词,returns 匹配列表中的第一个元素。例如,以下...
numbers.First(n => n % 2 == 0)
...returns numbers
中的第一个偶数。我想在 Racket 中做同样的事情。
我想到了以下...
(define (first-match f lst)
(first (filter f lst)))
...但我怀疑这可能非常低效,因为我认为它会在应用 first
之前过滤 整个 列表。 Linq 版本检查每个元素,因此只会遍历列表,直到找到匹配的元素。
任何人都可以证实或反驳我的假设,即我的 first-match
函数将遍历整个列表,如果是,我如何才能生成 Linq 的 First()
方法的更高效版本?
我尝试了以下版本的代码...
(define (first-match f lst)
(cond [(empty? lst) #f]
[(f (first lst)) (first lst)]
[else (first-match f (rest lst))]))
...只会遍历所需的距离,所以应该更有效率,但是 根据一些测试,这并没有快多少,这让我相信第一个版本没有遍历整个列表,或者第二个是。
有人可以发表评论吗? 谢谢
您的假设是正确的,即 (filter f lst)
在将结果传递给 first
之前将遍历整个输入列表(并在此基础上创建一个新列表!)。你的第二个版本效率更高,只会遍历列表直到找到元素。
但是在 Racket 中有一个更简单的解决方案,有一个内置程序可以完全你想要的:看findf
!
(findf even? '(1 3 5 2 4))
=> 2
(findf even? '(1 3 5 7 9))
=> #f