如何使用Scheme为列表中的每个数字实现一个计数器?

时间:2009-11-13 13:09:11

标签: list scheme counter

好的,我想计算每个[数字]在使用Scheme的列表中出现的次数。

我该怎么做?我还想存储给定数字的计数器并重新构建一个新列表。

例如,我有以下列表((1 2)(2 5)(5 7)(7 8)(6 8)(4 6)(3 4)(1 3)(4 8))

我在考虑先将列表弄平,然后为每个数字设置一个计数器(不知道该怎么做)。然后重新构建与原始编号对应的新列表。 (这可能很棘手?我需要存储一个临时变量?)

从这个例子说,数字1出现两次,数字2出现两次,数字3出现两次等...所以我想重新创建一个新列表,如下所示:

(1 2) (2 2) (3 2) (4 3) (5 2) (7 2) (6 2) (8 3)

任何想法我怎么能做到这一点?

更新

我正在考虑实现这样的增量计数器助手吗?

 (define inc-counter 
    (let ((counter 0)) 
      (lambda () (set! counter (+ counter 1))))) 

4 个答案:

答案 0 :(得分:3)

答案主要取决于您的实施(模数R6RS)。在PLT方案的情况下,这是一个快速定义。它避免了扁平化列表 - 您只需要扫描每个项目,因此在扫描树时如此简单,构建新副本毫无意义。此外,此函数对结果列表进行排序(因为它将在离开哈希表的过程中全部加扰)。即使您使用的是一些完全不同的实现,也应该很容易翻译:

(define (counts x)
  (define t (make-hash))
  (define (scan x)
    (if (list? x)
      (for-each scan x)
      (hash-set! t x (add1 (hash-ref t x 0)))))
  (scan x)
  (sort (hash-map t list) < #:key car))

(注意,顺便说一句,如果这是任何一种硬件问题,那么这段代码太实用了,无法作为答案...)

答案 1 :(得分:1)

使用accumulator参数展平,该参数保留每个参数列表的关联列表。这样你就可以获得每次循环所需的所有数据。

例如,您可以像这样编写阶乘:

(define (factorial num accum)
  (if (= num 0) accum (factorial (- num 1) (* accum num)))

并用(factorial 10 1)调用它。最后,累加器的值是函数的结果。在您的示例中,您将编写一个小帮助函数,该函数将调用flatten并跟踪每个数字出现的次数。

答案 2 :(得分:0)

也许不是最有效的解决方案,但我认为你可以通过partition列表的第一个元素来实现这一点,直到列表中没有更多的元素。然后,元素列表将是列表中与第一个数字相同的所有数字。可以在out-elements列表上重复此过程,直到列表中没有更多元素为止。

答案 3 :(得分:0)

您可以使用哈希表将数字映射到其出现次数。使用(make-hash)创建它。