您好,我是Scheme的新手。
我正在网上阅读教程,我想知道如何计算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)))))
答案 0 :(得分:3)
我认为bagify
和flatten
是这类问题的红色枷锁。当然,您可以使用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)))])))
解决嵌套列表的问题非常简单,一旦你为平面列表解决了它。
car
。car
和cdr
进行自然递归。null?
案例的左侧有意义的二元运算符组合,例如+
/ 0
,*
/ {{ 1}},1
/ cons
,'()
/ and
,#t
/ or
。