计算Scheme中嵌套列表中原子的出现次数

时间:2011-09-03 20:08:10

标签: recursion scheme

您好,我是Scheme的新手。

我正在网上阅读教程,我想知道如何计算Scheme中嵌套列表中原子的出现次数。我找到了一些提及bagifyflatten的教程;我试图混合它们但我收到了一个错误。可能有什么不对?

以下是代码:

(define (bagify lst)
  (foldl (lambda (key ht)
         (hash-update ht key add1 0))
       #hash() lst))

(define (flatten mylist)
  (cond ((null? mylist) '())
        ((list? (car mylist)) (append (flatten (car mylist)) (flatten (cdr mylist))))
        (else (cons (car mylist) (flatten (cdr mylist))) (bagify(mylist)))))

1 个答案:

答案 0 :(得分:3)

我认为bagifyflatten是这类问题的红色枷锁。当然,您可以使用flatten,然后计算生成的展平列表中的匹配项。但是,只需遍历嵌套列表就会更加高效和直接。

为简单起见,让我们从实现非嵌套情况的函数开始。这是一个计算'?出现次数的版本,更简单:

(define count-?s
  (lambda (ls)
    (cond
      [(null? ls) 0]
      [(eq? (car ls) '?) (add1 (count-?s (cdr ls)))]
      [else (count-?s (cdr ls))])))

将此更改为适用于嵌套列表只需添加一行cond行。您找到的flatten的实现包含一个提示:我们要检查递归的每一步是否列表的car本身是一个列表(但是,使用list?更多功率超出我们的需要;我们可以使用pair?代替,只要我们的输入始终是正确的嵌套列表。

一旦我们知道car也是(可能嵌套的)列表,我们需要将它传递给知道如何处理列表的函数。幸运的是,我们正在定义一个!

(define count-?s*
  (lambda (ls)
    (cond
      [(null? ls) 0]
      [(pair? (car ls)) (+ (count-?s* (car ls)) (count-?s* (cdr ls)))]
      [(eq? (car ls) '?) (add1 (count-?s* (cdr ls)))]
      [else (count-?s* (cdr ls))])))

这就是它的全部内容。很少考虑,不是吗?事实上,你只需要替换一对表达式并使用与嵌套列表完全不同的函数结束:

(define remove-?s*
  (lambda (ls)
    (cond
      [(null? ls) '()]
      [(pair? (car ls)) (cons (remove-?s* (car ls)) (remove-?s* (cdr ls)))]
      [(eq? (car ls) '?) (remove-?s* (cdr ls))]
      [else (cons (car ls) (remove-?s* (cdr ls)))])))

解决嵌套列表的问题非常简单,一旦你为平面列表解决了它。

  1. 从平面列表解决方案开始。
  2. 检查car
  3. 中的一对
  4. carcdr进行自然递归。
  5. 将答案与对null?案例的左侧有意义的二元运算符组合,例如+ / 0* / {{ 1}},1 / cons'() / and#t / or