删除元素列表

时间:2012-10-10 02:48:29

标签: scheme racket

有人告诉我这段代码有什么问题。我以为我掌握了一些解决朋友问题的计划技巧,但最终弄得头脑发热。我想删除列表中的所有类似元素。之前它只删除了我想删除的第一个元素,但现在它删除了汽车和我要删除的第一个元素。我正在寻找像(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)))))

2 个答案:

答案 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))))))