這是因爲這個條件:
((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
,如果你有一個更復雜的程序來實現。)