有人告诉我这段代码有什么问题。我以为我掌握了一些解决朋友问题的计划技巧,但最终弄得头脑发热。我想删除列表中的所有类似元素。之前它只删除了我想删除的第一个元素,但现在它删除了汽车和我要删除的第一个元素。我正在寻找像(delete 3 (list 2 3 4 3 5 3))
这样的输出,返回(2 4 5)。
(define (delete n lst)
(cond
((null? lst) null)
((equal? n (car lst)) (cdr lst))
(else
(remove n (cdr lst)))))
答案 0 :(得分:4)
这是因为有条件:
((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
中的第一个元素(注意它不会将其附加到干净数字列表中)。
如果第一个元素不是目标号码,则会到达else,将lst
的第一个值追加到clean
的末尾,然后再次调用delete。
(请注意,此代码使用尾递归,这是一种编写递归方法的方法,用于跟踪每个递归调用的中间值,而不是“常规”递归,它在在下面,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
实现。)
答案 1 :(得分:0)
以下是我提出的建议:
(define (delete n lst)
(cond ((empty? lst) lst)
((= (car lst) n) (delete n (cdr lst)))
(else (append (list (car lst)) (delete n (cdr lst))))))