如何在Racket语言中为嵌套列表创建计数器?

时间:2016-03-19 03:00:58

标签: list nested racket counter nested-lists

我试图在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))))))

2 个答案:

答案 0 :(得分: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,你想在第二个中计算

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

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

答案 1 :(得分:1)

由于你现在有了一个可行的解决方案,我会告诉你

替代您的工作代码

 
(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递归调用中,包括附加的递归调用。