这似乎是一个大问题,但在以下3种计算真实项目数量的方法方面是否有任何显着差异?
#lang racket
(define (counttrue . vars)
(length (remove* (list #f) vars)) )
(define (counttrue2 . vars)
(define c 0)
(for ((item vars))
(when item (set! c (add1 c))))
c )
(define (counttrue3 . vars)
(count (lambda(x) x) vars) )
它们都会产生相同的结果,但有没有理由为什么应该或不应该选择特定的?
编辑:关于使用时间功能,以下3个函数获得以下结果,2个来自@ ChrisJester-Young和@Sylwester的答案:
"---------- counttrue ------------"
cpu time: 751 real time: 751 gc time: 16
"---------- counttrue2 ------------"
cpu time: 946 real time: 947 gc time: 10
"---------- counttrue3 ------------"
cpu time: 456 real time: 457 gc time: 8
"---------- counttrue_chris1 ------------"
cpu time: 726 real time: 727 gc time: 9
"---------- counttrue_chris2 ------------"
cpu time: 595 real time: 595 gc time: 8
"---------- counttrue_sylwester1 ------------"
cpu time: 543 real time: 544 gc time: 7
"---------- counttrue_sylwester2 ------------"
cpu time: 515 real time: 515 gc time: 7
因此,“计数lambda”方法是最快的。
答案 0 :(得分:3)
count
版本可能是最惯用的版本(除非我将其写为(count identity items)
)。此外,set!
版本绝对不是惯用的Racket,而Racket并没有优化其使用,正如您可以从时序测试中看到的那样。
以下是您的计时乐趣的几种选择:
使用for
理解:
(for/sum ((x (in-list items)) #:when x) 1)
手动循环:
(let loop ((sum 0)
(items items))
(cond ((null? items) sum)
((car items) (loop (add1 sum) (cdr items)))
(else (loop sum (cdr items)))))
答案 1 :(得分:2)
他们只是做同样的不同方式。所有这些都是O(n)因此它们在时间上没有太大差别。他们中的一些人通过拥有一个中间名单而浪费了一点点记忆,但我认为你浪费了更多的时间进行比较,而不是通过选择最快的一个回来。我会根据你的第三个来选择那个最短且最重要的那个:
(define (count-true . args)
(count values args))
它实际上只是一个专门的折叠:
(define (count-true . args)
(foldl (lambda (val sum)
(if val (add1 sum) sum))
0
args))
count
和foldl
都在let
中使用名为#!racket
的方式实施。