这是因为这个条件:
((equal? n (car lst)) (cdr lst))
什么这行代码它会检查n
是一样的,在列表中的第一个元素。如果是,它会返回列表的其余部分。由于您的目标元素是列表的第二个元素,它会从第三个元素开始返回列表的其余部分。列表中的第一个元素被完全删除。你目前没有跟踪你已经检查过的OK元素。
从您的代码看来,您希望遍历列表中的元素,并且如果找到目标值,请致电remove
。如果你想以这种方式实现它,你还需要跟踪你所检查和验证的值,这些值不是你的目标值。所以你的功能需要三个参数:n
,你的目标; lst
要检查的剩余数字;和clean
(或任何你想称之为)的数字。
这是你的算法的一个工作版本:
(define (delete n lst clean)
(cond
((empty? lst) clean)
((equal? n (car lst)) (delete n (cdr lst) clean))
(else
(delete n (cdr lst) (append clean (list (car lst)))))))
你会调用它像这样:(delete 3 (list 2 3 4 3 5 3) '())
首先,如果你有号码留下来检查检查。如果你不这样做,它会返回你的清单。
然后检查第一个元素是否与您的目标元素匹配。如果确实如此,那么它会再次调用delete,从而有效地删除lst
中的第一个元素(请注意,它不会将其附加到干净的数字列表中)。
的意外,如果第一个元素是不目标数时达到,追加的lst
第一值的clean
末和电话再次删除。
(请注意,此代码使用尾递归,这是编写跟踪与每个递归调用的中间值的递归方法的一种方式,而不是“规则的”递归,做计算在最后。Samrat的的回答,下面是一个常规的递归解决方案。讨论尾递归can be found here。)
从您的文章中,它听起来像是要删除目标编号的所有实例。除了使用remove
函数(仅删除目标编号的第一个实例)之外,您应该使用remove*
函数来查看,该函数将删除所有实例。这将大大简化您的功能。所以,从列表中删除的3所有情况下,这就够了:
(remove* '(3) (list 2 3 4 3 5 3))
如果你想将其包装在一个函数:
(define (delete n lst)
(remove* (list n) lst))
你应该上一般map functions读了,因为他们几乎做你想要的。 (它们适用于对列表中的所有元素的过程;上面也可以用一个filter-map
,如果你有一个更复杂的程序来实现。)