Scheme 从列表中删除元素
有人告诉我这个代码有什么问题。我以为我掌握了一些解决朋友问题的技巧,但结果弄糊涂了。我正在尝试从列表中删除所有类似的元素。之前它只移除了我想移除的第一个元素,但现在它移除了汽车和我想移除的第一个元素。我正在寻找这样的输出:Scheme 从列表中删除元素,scheme,racket,Scheme,Racket,有人告诉我这个代码有什么问题。我以为我掌握了一些解决朋友问题的技巧,但结果弄糊涂了。我正在尝试从列表中删除所有类似的元素。之前它只移除了我想移除的第一个元素,但现在它移除了汽车和我想移除的第一个元素。我正在寻找这样的输出:(delete 3(list 2 3 4 3 5 3)),returns(2 4 5) 这是因为这个条件: ((equal? n (car lst)) (cdr lst)) 此行的作用是检查n是否与列表中的第一个元素相同。如果是,则返回列表的其余部分。因为您的目标元素是列表的
(delete 3(list 2 3 4 3 5 3))
,returns(2 4 5)
这是因为这个条件:
((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)))))))
您可以这样称呼它:(删除3(列表2 3 4 3 5 3))
首先,它会检查您是否还有需要检查的数字。如果您没有,它将返回您的干净列表
然后检查第一个元素是否与目标元素匹配。如果是,则再次调用delete,有效地删除lst
中的第一个元素(注意,它不会将其附加到干净的数字列表中)
如果第一个元素不是目标编号,则会到达else,它将lst
的第一个值附加到clean
的末尾,并再次调用delete
(请注意,此代码使用尾部递归,这是一种编写递归方法的方法,用于跟踪每次递归调用的中间值,而不是在最后进行计算的“常规”递归。下面Samrat的回答是一个常规递归解决方案。尾部递归的讨论。)
从您的帖子中,听起来您希望删除目标编号的所有实例。与其使用remove
函数(只删除目标编号的第一个实例),不如考虑使用remove*
函数(删除所有实例)。这将大大简化您的功能。因此,要从列表中删除3的所有实例,这就足够了:
(remove* '(3) (list 2 3 4 3 5 3))
如果要将其包装到函数中:
(define (delete n lst)
(remove* (list n) lst))
一般来说,你应该仔细阅读,因为他们基本上都是你想要的。(它们对列表中的所有元素应用一个过程;如果您有一个更复杂的过程,也可以使用
过滤器映射来实现上述操作。)这是由于以下条件:
((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)))))))
您可以这样称呼它:(删除3(列表2 3 4 3 5 3))
首先,它会检查您是否还有需要检查的数字。如果您没有,它将返回您的干净列表
然后检查第一个元素是否与目标元素匹配。如果是,则再次调用delete,有效地删除lst
中的第一个元素(注意,它不会将其附加到干净的数字列表中)
如果第一个元素不是目标编号,则会到达else,它将lst
的第一个值附加到clean
的末尾,并再次调用delete
(请注意,此代码使用尾部递归,这是一种编写递归方法的方法,用于跟踪每次递归调用的中间值,而不是在最后进行计算的“常规”递归。下面Samrat的回答是一个常规递归解决方案。尾部递归的讨论。)
从您的帖子中,听起来您希望删除目标编号的所有实例。与其使用remove
函数(只删除目标编号的第一个实例),不如考虑使用remove*
函数(删除所有实例)。这将大大简化您的功能。因此,要从列表中删除3的所有实例,这就足够了:
(remove* '(3) (list 2 3 4 3 5 3))
如果要将其包装到函数中:
(define (delete n lst)
(remove* (list n) lst))
一般来说,你应该仔细阅读,因为他们基本上都是你想要的。(它们对列表中的所有元素应用一个过程;如果您有一个更复杂的过程,也可以使用过滤器映射来实现上述操作。)以下是我的想法:
(define (delete n lst)
(cond ((empty? lst) lst)
((= (car lst) n) (delete n (cdr lst)))
(else (append (list (car lst)) (delete n (cdr lst))))))
以下是我的想法:
(define (delete n lst)
(cond ((empty? lst) lst)
((= (car lst) n) (delete n (cdr lst)))
(else (append (list (car lst)) (delete n (cdr lst))))))