1

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

我怎样才能做到这一点 ?我还想存储给定数字的计数器并重新构建一个新列表。

例如,我有以下列表((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

4 回答 4

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))

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

于 2009-11-13T14:19:48.260 回答
1

使用累加器参数进行展平,该参数保留每个出现次数的关联列表。这样,您每次在循环中都会获得所需的所有数据。

例如,你可以这样写阶乘:

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

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

于 2009-11-13T13:37:44.503 回答
0

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

于 2009-11-13T13:38:26.717 回答
0

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

于 2009-11-13T13:53:36.187 回答