(define (num-zeroes lst)
(define (helper lst sofar)
(cond ((null? lst) sofar)
((list? (car lst)) (helper (car lst) sofar))
((eq? lst 0) (helper (cdr lst) (+ 1 sofar)))
(else
(helper (cdr lst) sofar))))
(helper lst 0))
此函数用于计算列表中的0数。但是,当我输入值时,它一直给我0。我怎么能解决这个问题?
答案 0 :(得分:1)
在第三种情况下,您要将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表示它从 l eft到右侧)列表处理嵌套:
(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))))
希望这有帮助。