在您的第三个条件中,您将 lst 与 0 进行比较。这应该是 (car lst)。
由于您的 (list? (car lst)) 条件,您似乎想要计算嵌套列表。在当前实现中存在一个问题(上述检查已修复),因为条件不会将列表的单独部分相加。
例如,
(num-zeroes '(0 0 (1 0) (1 0 0))) ; => 3
要解决此问题,您可以执行以下操作:
(define (num-zeroes lst)
(define (helper lst sofar)
(cond ((null? lst) sofar)
((list? (car lst)) (+ sofar ;; add sofar to
(helper (car lst) 0) ;; branched out first part
(helper (cdr lst) 0))) ;; and branched rest
((eq? (car lst) 0) (helper (cdr lst) (+ 1 sofar))) ;; (car lst), not lst
(else
(helper (cdr lst) sofar))))
(helper lst 0))
这导致:
(num-zeroes '(0 0 (1 (1 (0 0) 0)) (1 0 0))) ;; => 7
现在,您想要对集合做某事并保持累积值的问题发生了很多变化。 fold 是专为这些问题设计的高阶函数。
Fold 接受一个带有两个参数(一个元素和一个累加器)、一个起始值和一个集合的函数。它依次将函数应用于集合的每个元素,最后返回累加器。
在您的情况下,当元素为 0 时,可以只将 1 添加到累加器,并将扁平列表(flatten 从列表中删除嵌套)传递给foldl(参见https://docs.racket-lang.org/reference/pairs.html#%28def._%28%28lib._racket%2Fprivate%2Flist..rkt%29._foldl%29%29)(l表示它从 left 到 right) 遍历列表来处理嵌套:
(define (num-zeroes2 lst)
(foldl (lambda (e acc)
(if (= e 0)
(+ acc 1)
acc))
0
(flatten lst)))
这导致相同的结果:
(num-zeroes2 '(0 0 (1 (1 (0 0) 0)) (1 0 0))) ;; => 7
或者,考虑一下,您也可以flatten 列表和filter 取出所有等于 0 的值(有一个称为 zero? 的库方法),并计算元素:
(define (num-zeroes3 lst)
(length
(filter zero? (flatten lst))))
希望这会有所帮助。