【问题标题】:Counting number of zeroes in lists in scheme计算方案中列表中的零数
【发布时间】:2016-10-18 19:21:07
【问题描述】:
(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。我该如何解决这个问题?

【问题讨论】:

标签: list scheme racket


【解决方案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表示它从 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))))

希望这会有所帮助。

【讨论】:

  • 这是一个品味问题,但值得一提的是,num-zeroes3 可以使用compose 进一步简化。例如((compose length (curry filter zero?) flatten) lst)
  • @pdoherty926 我不知道 Scheme 中的 compose,但嵌套较少看起来不错。 :)
猜你喜欢
  • 1970-01-01
  • 2020-08-23
  • 1970-01-01
  • 1970-01-01
  • 2015-07-21
  • 1970-01-01
  • 2018-11-06
  • 2019-01-03
  • 1970-01-01
相关资源
最近更新 更多