2012-10-10 131 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))))))