我试图从列表中删除最后一次出现的值,并且在使用嵌套列表的递归调用期间我的程序失败。
我有一个计算符号出现次数的函数:
(define (countOccurrences lst elem count)
(cond
[(empty? lst) count]
[(list? (car lst)) (countOccurrences (cdr lst) elem
(countOccurrences (car lst) elem count))]
[(equal? (car lst) elem) (countOccurrences (cdr lst) elem (add1 count))]
[else (countOccurrences (cdr lst) elem count)]))
主体在这里:
(define (lastLess lst elem)
(let ((count (countOccurrences lst elem 0)))
(if (< 0 count)
(lastLessHelper lst elem count)
lst)))
辅助功能:
(define (lastLessHelper lst elem count)
(cond
[(empty? lst) empty]
[(eq? count 0) (cdr lst)]
[(eq? (car lst) elem) (set! count (sub1 count))
(cond
[(eq? count 0) (cdr lst)]
[else (cons (car lst)
(lastLessHelper (cdr lst) elem count))])]
[(list? (car lst)) (cons (lastLessHelper (car lst) elem count)
(lastLessHelper (cdr lst) elem count))]
[else (cons (car lst) (lastLessHelper (cdr lst) elem count))]))
问题在于这一行:
[(list? (car lst)) (cons (lastLessHelper (car lst) elem count) (lastLessHelper (cdr lst) elem count))]
我递减计数&#39;变量(car lst)
等于elem
时,并且在第一次递归调用(lastLessHelper (car lst) elem count)
期间它会正确递减,但是当该调用返回并且它在cdr lst上递归时:(lastLessHelper (cdr lst) elem count))]
&#39; count&#39;的价值返回原始值。
适用于普通列表输入,例如(lastLess '(1 2 3 2 4 5) '2))
我正确获取(1 2 3 4 5)
,但是当使用嵌套列表作为输入时,例如(lastLess '(1 (2 3) 4 2 5) '2)
,它返回(1 (2 3) 4 2 5)
。
如何保持&#39;计数&#39;在递归调用期间?我应该注意,有可能更简单的方法来做到这一点,但这是一个家庭作业,我们被禁止使用“反向”#39;调用
编辑:Sylwester的评论帮助我理解。我的问题不是计算项目的出现次数,问题是要删除最后一次出现的项目。我的想法是首先计算该项目的出现次数,然后遍历列表并递减该计数直到它为0,然后我知道要删除该项目,然后仅cons
列表的其余部分。
答案 0 :(得分:2)
您永远不需要使用set!
(define (count-matches needle haystack)
;; helper
(define (count-matches count haystack)
(cond ((equal? needle haystack) (+ count 1))
((pair? haystack)
(count-matches (count-matches count (car haystack))
(cdr haystack)))
(else count)))
;; call helper
(count-matches 0 haystack))
(count-matches 2 '(1 (2 3) 4 2 5)) ; ==> 2
如您所见,我们在count
中使用car
进行递归,并在count
的递归中使用返回值作为cdr
。
答案 1 :(得分:1)
你甚至不需要计数器变量或帮助程序,只需返回每个部分结果并累积递归调用的子结果。试试这个,使用标准模板遍历列表列表:
(define (count-matches ele lst)
(cond ((null? lst) ; if the list is empty
0) ; return default value
((not (pair? lst)) ; if this is a single element
(if (equal? lst ele) 1 0)) ; check if it matches
(else ; otherwise accumulate results of
(+ (count-matches ele (car lst)) ; the `car` part
(count-matches ele (cdr lst)))))) ; and the `cdr` part
例如:
(count-matches 'x '(1 (x 2) 3 x (4 (5 x)) 6 (x)))
=> 4