【问题标题】:How can I create a counter for a nested list in the Racket language?如何在 Racket 语言中为嵌套列表创建计数器?
【发布时间】:2016-07-05 23:19:00
【问题描述】:

我正在尝试在 Dr Racket 中创建一个计数器,该计数器将遍历嵌套列表并输出计数。

I currently have this code(我把所有的3都留在了列表中)

目前正在输出 3(这些是前三个 3) 我假设它已经到达第一个嵌套列表的末尾并在该点停止,但我似乎不知道该怎么做。 (是的,这是一个任务,但这是我们在球拍中的第二个任务,也是春假期间的第二个任务。它是我们回去的那一天)

    (define (genCounter lst target c)
      (cond
         ((empty? lst) c)
         ((list? (first lst))
          (genCounter (first lst) target c))
         ((eq? (first lst) target)
          (genCounter (rest lst) target (+ c 1)))
         (else
          (genCounter (rest lst) target c))))

我不指望你给我答案,而只是解释应该改变什么,或者比我的教授教我更多关于语言的知识。

所以我将列表更改为 (genCounter '(3 (3 3 (3 3 3)) 3 (3 (3))) 3 0) 并返回 6(我测试发现它是前 6 个被退回。我相信当涉及到其中一个列表的末尾时,它会停止执行该函数,但是就像我说的,我不确切知道要实现什么来修复它(尽管我知道出了什么问题和它)。

这是我最终创建的内容:

     (define (genCounter lst target)
      (if (null? lst) 0
          (let ((current (first lst)))
            (cond
              ((list? current)
               (+ (genCounter current target) (genCounter (rest lst) target)))
              ((eq? current target)
               (+ 1 (genCounter (rest lst) target)))
              (else
               (genCounter (rest lst) target))))))

【问题讨论】:

  • 发布您的代码而不是代码图像。
  • 我已经更新它以包含实际代码。

标签: list nested racket counter nested-lists


【解决方案1】:

首先,我们不要将标识符命名为listlist 是一个构造列表的函数。如果您使用此名称,您将隐藏它,因此将无法在函数中使用它!下面,我将改用lst

现在,对于您的问题,答案是,您的第二个分支是错误的:

[(list? (first lst)) (genCounter (first lst) val c)]

它的作用是:“如果第一个元素是一个列表,则深入这个子列表,计数,然后回答”。

你能看出为什么不对吗?

假设您想在以下列表中数 2:

(list (list 2 2 2) 2 (list 2 (list 2)))

因为第一个元素(list 2 2 2)是一个列表,它潜入这个子列表并计数为2。答案是3。但是,预期的输出是6!

问题是,你不想只在第一个元素中计算 2,你想在 2 中计算

(list ... >>> 2 (list 2 (list 2)) <<<)

也是。

也就是说,你想在列表的其余部分中计算 2,在第一个元素中计算 2 之后,然后将它们相加。

【讨论】:

  • 我明白你在说什么(它在第一个子列表之后结束),但我并没有真正看到我如何解决它。我需要在某个时候浏览列表的其余部分,但我不太清楚如何或在什么时候实现它。我是否应该设置一些语句,在列表的第一个元素的末尾,它进入“休息”?
  • 当您遇到一个列表元素时,您的总体结果是该子列表的计数 + 初始列表其余部分的计数。
【解决方案2】:

既然你现在有一个可行的解决方案,我会告诉你

工作代码的替代方案

(define (genCounter lst target)
  (if (empty? lst)
      0
      (+ (genCounter (rest lst) target) 
         (let ((x (first lst)))
           (if (list? x)
               (genCounter x target) 
               (if (eqv? x target) 1 0))))))

注意

  • 代码中的冗余更少,代价是在第一个元素不匹配时添加0
  • 你不应该使用eq?作为数字,而应该使用=eqv?;也看看equal?

适用于累加器的代码(如您的第一个版本)

(define (genCounter lst target)
  (let loop ((lst lst) (count 0))
    (if (empty? lst)
        count
        (loop (rest lst)
              (let ((x (first lst)))
                (if (list? x)
                    (loop x count)
                    (if (eqv? x target) (add1 count) count)))))))

感兴趣的:

  • 我将累加器 count 移动到了一个内部过程(在这种情况下是一个命名的 let),它不应该是主过程签名的一部分
  • 所有的魔法都发生在最后对loop 的递归调用中,如果第一个元素是一个列表,则包括一个附加递归调用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-11
    • 2022-01-16
    • 2011-07-29
    • 1970-01-01
    • 2016-09-18
    • 2011-06-11
    相关资源
    最近更新 更多