2017-01-02 33 views
0

我試圖從列表中的任何級別刪除列表中的所有元素。 我需要使用地圖功能,雖然。我正在使用Common Lisp。比如我希望能夠做到:從非線性列表中刪除項目的發生

(fdelete '(1 2 3 4 (3)) 3) => (1 2 4) 

我試過到目前爲止: 這個函數會做什麼需要,排序的。它將用NIL替換給定元素的所有出現,所以它不完全是我想要的。

(defun fdelete (l e) 
    (cond 
     ((null l) 0) 
     ((equal l e) nil) 
     ((atom l) l) 
     (t (mapcar (lambda(l) (fdelete l e)) l)) 
    ) 
) 

這將做

(fdelete '(1 2 3 4 (3)) 3) => (1 2 NIL 4 (NIL)) 

我的第二次嘗試與mapcap功能,因爲這一個不會返回一個列表相同大小的輸入列表。 這將完成所需的任務,但它會'摧毀'我的初始列表,因爲它會將所有子列表'浮出水面'。

(defun fdelete (l e) 
    (cond 
     ((null l) 0) 
     ((equal l e) nil) 
     ((atom l) (list l)) 
     (t(mapcan(lambda(x) (fdelete x e))l)) 
    ) 
) 

所以這確實是不(fdelete '(1 2 3 4 (3)) 3) => (1 2 4) 但它也將這樣做不對,如果我例如試試這個:

(fdelete '(1 2 3 (4) (3)) 3)) => (1 2 4) 

我想要它做的(fdelete '(1 2 3 (4) (3)) 3)) => (1 2 (4))

我希望我的問題結構良好且足夠詳細,我正在提供工作示例。有人可以給我一些關於如何解決這個問題的提示嗎?

+0

是'reduce'認爲是「地圖功能」? – Sylwester

+0

不,問題表明我必須使用mapcon,mapcan,mapcar或maplist。這不是家庭作業順便說一句,我只是練習即將到來的考試。 – MikhaelM

+1

它應該是'(fdelete'(1 2 3 4(3))3)=>(1 2 4())'',因爲'(fdelete'(3)3)=>()'。 –

回答

2

使用mapcan是正確的選擇,因爲您可以用list換行來獲取值或使用nil來刪除項目。對於list元素,如果它尚未匹配要刪除的元素,則應檢查遞歸的結果,並將其包裝(如果它不是空列表)。

該解決方案看起來是這樣的:

(defun remove-deep (item list) 
    (mapcan (lambda (cur) 
      (cond ((equal item cur) '()) 
        ...)) 
      list)) 

(remove-deep 3 '(1 nil 2 3 (3) (3 4))) 
; ==> (1 nil 2 (4)) 

要應用principle of least surprise我已經改名功能,因爲deleteremove破壞性版本。此外,我不停的standard functions的參數順序:

+0

'{3(3)} ==>()'因此它必須是'{3(1 3(3))} ==>(1())''。 –

+0

@WillNess我同意放棄空列表以及'item'是非常規的。不看天賦,我會期待我的測試結果是'(1零個2零(4))'這是簡單,因爲你只是包裝遞歸不管,但是OP指定也省略列出了已經變空就像我的測試一樣。 – Sylwester

+0

是的,我認爲他們在那裏是錯誤的。我去了簡單的英語,和一致性:從(13)除去3給了我們(1),因此,從(3) - (),因此,從消除3(1 3(3))必須給我們(1() )。 –