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

Recursion 计算Scheme中嵌套列表中原子的出现次数,recursion,scheme,Recursion,Scheme,你好,我是新来的 我正在网上阅读教程,我想知道如何计算Scheme中嵌套列表中原子的出现次数。我发现一些教程提到了bagify和flatten;我试着把它们混在一起,但我弄错了。有什么不对劲吗 代码如下: (define (bagify lst) (foldl (lambda (key ht) (hash-update ht key add1 0)) #hash() lst)) (define (flatten mylist) (cond ((null?

你好,我是新来的

我正在网上阅读教程,我想知道如何计算Scheme中嵌套列表中原子的出现次数。我发现一些教程提到了
bagify
flatten
;我试着把它们混在一起,但我弄错了。有什么不对劲吗

代码如下:

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

我认为,
bagify
flatte
是解决这类问题的挡箭牌。当然,您可以使用
展平
,然后计算结果展平列表中的出现次数。但是,只遍历嵌套列表更有效、更直接

为了简单起见,让我们从实现非嵌套案例的函数开始。以下是一个统计
出现次数的版本,更为简单:

(define count-?s
  (lambda (ls)
    (cond
      [(null? ls) 0]
      [(eq? (car ls) '?) (add1 (count-?s (cdr ls)))]
      [else (count-?s (cdr ls))])))
将其更改为在嵌套列表上工作只需要添加一行
cond
。您发现的
plant
的实现在这里包含一个提示:我们希望在递归的每个步骤检查列表的
car
本身是否是一个列表(但是,使用
list?
比我们需要的更强大;我们可以使用
pair?
,只要我们的输入始终是一个正确的嵌套列表)

一旦我们知道
car
也是一个(可能嵌套的)列表,我们就需要将它传递给一个知道如何处理列表的函数。幸运的是,我们正在定义一个!p>
(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)))])))
解决嵌套列表的问题非常容易,只要解决了平面列表的问题

  • 从平面列表解决方案开始
  • 检查
    车中是否有一对
  • 汽车
    cdr
    执行自然递归
  • 将答案与一个二进制运算符结合起来,该运算符在
    null?
    案例的左侧有意义,例如
    +
    /
    0
    *
    /
    1
    cons
    /
    '()
    /
    /

  • 我认为,
    bagify
    flatte
    是解决这类问题的挡箭牌。当然,您可以使用
    展平
    ,然后计算结果展平列表中的出现次数。但是,只遍历嵌套列表更有效、更直接

    为了简单起见,让我们从实现非嵌套案例的函数开始。以下是一个统计
    出现次数的版本,更为简单:

    (define count-?s
      (lambda (ls)
        (cond
          [(null? ls) 0]
          [(eq? (car ls) '?) (add1 (count-?s (cdr ls)))]
          [else (count-?s (cdr ls))])))
    
    将其更改为在嵌套列表上工作只需要添加一行
    cond
    。您发现的
    plant
    的实现在这里包含一个提示:我们希望在递归的每个步骤检查列表的
    car
    本身是否是一个列表(但是,使用
    list?
    比我们需要的更强大;我们可以使用
    pair?
    ,只要我们的输入始终是一个正确的嵌套列表)

    一旦我们知道
    car
    也是一个(可能嵌套的)列表,我们就需要将它传递给一个知道如何处理列表的函数。幸运的是,我们正在定义一个!p>
    (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)))])))
    
    解决嵌套列表的问题非常容易,只要解决了平面列表的问题

  • 从平面列表解决方案开始
  • 检查
    车中是否有一对
  • 汽车
    cdr
    执行自然递归
  • 将答案与一个二进制运算符结合起来,该运算符在
    null?
    案例的左侧有意义,例如
    +
    /
    0
    *
    /
    1
    cons
    /
    '()
    /
    /

  • 哇!非常感谢你。。。Scheme对我来说有点奇怪,但它很有趣。再次感谢您。=)哇!非常感谢你。。。Scheme对我来说有点奇怪,但它很有趣。再次感谢您。=)