0

Someone tell me what is wrong with this code. I thought I mastered a few scheme skills to solve a friend's problem but it ended up messing my head. I am trying to remove all similar elements off the list. Earlier it was removing only the first element I want to remove, but now its removing the car and the first element f what I want to remove. I am looking for an output like: (delete 3 (list 2 3 4 3 5 3)), returns (2 4 5).

(define (delete n lst)
    (cond 
         ((null? lst) null)
         ((equal? n (car lst)) (cdr lst))
         (else
             (remove n (cdr lst)))))
4

2 回答 2

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 的答案是常规的递归解决方案。关于尾递归的讨论可以在这里找到。)

从您的帖子中,听起来您想删除目标编号的所有实例。而不是使用这个remove函数——它只删除目标编号的第一个实例——你应该看看使用这个remove*函数,它会删除所有实例。这将大大简化您的功能。因此,要从列表中删除 3 的所有实例,这就足够了:

(remove* '(3) (list 2 3 4 3 5 3))

如果你想把它包装在一个函数中:

(define (delete n lst)
  (remove* (list n) lst))

一般来说,您应该阅读地图功能,因为它们几乎可以满足您的需求。filter-map(他们对列表中的所有元素应用一个过程;如果你有一个更复杂的过程,上面也可以用 a 来实现。)

于 2012-10-10T03:10:58.900 回答
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))))))
于 2012-10-10T03:27:44.363 回答