2012-10-10 133 views
0

有人告诉我这段代码有什么问题。我以为我掌握了一些方案技巧来解决朋友的问题,但结果弄乱了我的头脑。我正试图从列表中删除所有类似的元素。早些时候,它只是删除我想要删除的第一个元素,但现在它删除了汽车,并删除了我想删除的第一个元素。我正在寻找一个输出,如:(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))))) 

回答

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中的第一个元素(请注意,它不会将其附加到干净的数字列表中)。

的意外,如果第一个元素是目标数时达到,追加的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,如果你有一个更复杂的程序来实现。)

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