【问题标题】:Scheme list counting function方案列表计数功能
【发布时间】:2012-10-22 14:43:19
【问题描述】:

我正在尝试编写一个计算列表中所有项目的 Scheme 函数,但与可用的长度函数不同,它也会计算内部列表,因此 countAll '(a (a b)) 将返回 3 而不是 2。

第一个检查是一个空列表,第二个应该检查列表的头部当前是否是一个列表本身,然后它应该将该列表的长度添加到总数中并调用下一个递归调用,如果不是,它应该简单地跳到第三部分,这将对总数加一并递归调用函数。

我遇到语法错误,我不确定我的方法。我会以正确的方式解决这个问题吗?有没有更好/更简单的方法来做到这一点?

(define countAll 
  (lambda (list)

    (if (null? list)
        0

        ((if (list? (car list)
                    (+ length (car list)
                       (countAll (cdr list))))))

        (+ 1
           (countAll (cdr list))))))     
  (+ 1
   (countAll(cdr list)
  )))))

【问题讨论】:

  • 我已经根据程序的结构编辑了问题以引入缩进。缩进如此怪异的事实应该暗示程序结构不太正确。

标签: list recursion count scheme


【解决方案1】:

你把括号弄乱了。我强烈建议使用 cond 重写它,如

(cond
  ((null? lst) 0)
  ((list? (car lst)) (???))
  (else (???)))

这将使您更容易看到您在做什么,并且不太可能弄乱括号。除非在最简单的情况下,否则嵌套 if 确实是应该避免的。

你的方法几乎是正确的,但你错过了一些东西。您对(list? (car lst)) 评估为真时会发生什么做出了 假设。你能想到它是什么吗?如果你仔细想想,你会意识到你不能在这里使用 length 函数。

【讨论】:

  • 例如,如果原始函数输入是 (a (a b c) d),在第一次通过时,两个评估都会失败并且会发生递归,从而使输入到下一次迭代 ( (a b c) d) 据我了解 (list? (car lst)) 应该从上一个列表中评估 (a b c) ,然后长度函数将计算它。如果它不是列表,则代码将不会执行。我错过了什么!?
  • '(a (a (a b) c) d) 会发生什么?
【解决方案2】:

此类问题的解决方案遵循一个众所周知的结构,如果您愿意,可以使用一种方法,用于遍历列表。这看起来像家庭作业,所以我会帮助你大致了解一下,然后你继续填写空白:

(define (countAll lst)
  (cond ((null? lst)               ; if the list is empty.
         <???>)                    ; then it doesn't have any elements
        ((not (list? (car lst)))   ; if the first element in the list is not a list
         (<???> (countAll <???>))) ; add one and advance the recursion over the `cdr`
        (else                      ; otherwise
         (+ (countAll <???>)       ; add the result of the recursion over the `car`
            (countAll <???>)))))   ; with the result of the recursion over the `cdr`

如果您需要更多帮助来了解如何为此类处理列表的问题构建解决方案,我建议您查看The Little SchemerHow to Design Programs,这两本书都会教您如何grok 递归过程。

【讨论】:

  • 我认为 pair? 只有在恰好是两个值的情况下才会返回 true?例如。 (pair? '(1 2)) -> #t, (pair? '(1 2 3)) -> #f?
  • @RoddyoftheFrozenPeas 然后您设法忽略了所有文档。列表本质上是链对。
  • @RoddyoftheFrozenPeas 不,如果传递的参数是cons-cell,pair? 返回true。特别是,任何非空列表都是一对。
  • 奥斯卡,我认为您的回答在上下文中很有帮助。你已经明确地展示了如何做我让他考虑的事情。你至少可以给他一些时间来反思。
  • 然而documentation 却说“一对恰好结合了两个值”,这就是我对它的使用感到困惑的原因。
【解决方案3】:

如果你想计算嵌套列表的元素,你可以使用深度递归函数,正如一些人在这里回答的那样。或者我所做的是使用球拍功能(展平)使嵌套列表变平,然后在 1 级列表上使用递归,如下面的代码

  (define (howMany ls)
  (if (null? ls)
  0
  (+ 1 (howMany (cdr ( flatten ls  )))))) ; flat the nested list and deal with it as a level 1 list.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-04-05
    • 2012-02-03
    • 1970-01-01
    • 2023-04-04
    • 1970-01-01
    • 1970-01-01
    • 2011-03-22
    • 1970-01-01
    相关资源
    最近更新 更多