2017-10-06 135 views
1

我想刪除列表中每個列表的第一個元素。 例如,要列出[[1,2],[3,4]],我應該返回[[2],[4]]。 在大多數情況下,下面這段代碼將正常工作:從Prolog列表中的列表中刪除每個列表中的第一個元素的最佳方法?

remove_firstElem([],[]). 
remove_firstElem([[_H|T]|Ls],[T|L]) :- 
    remove_firstElem(Ls,L). 

但對於像[[1],[2],我想列出它返回[]而不是[[] [] 。

我試過到目前爲止是這樣的:

remove_firstElem([_H|Ls],L) :- 
    length(_H,1), 
    remove_firstElem(Ls,L). 

但它返回[ ],[[ ]],[[ ]],[[ ],[ ]],我真的不知道有什麼地方錯了。

任何人都可以幫助我解決它嗎?謝謝你的幫助!

+0

如果沒有在源空列表。像'remove_firstElem([[]],L)'。 –

+0

to [[]]它應該返回[],它返回的列表中不應該有空列表。 – Fallin

回答

1

如果我理解正確,你想彈出列表的頭部,但萬一列表只包含一個元素(或根本沒有),應該刪除該列表。

我們可以檢查子列表至少包含兩個元素與圖案:

pop_lists([[_,H2|T]|TA],[[H2|T]|TB]) :- 
    pop_lists(TA,TB). 

所以在這裏我們有第一個列表模式[_,H2|T]_與第一個元素綁定,第二個元素與H2綁定,其餘元素與尾部綁定。

無法與該模式統一的列表是空列表或帶有一個元素的列表。因此,在這種情況下,我們完全無視:

pop_lists([[]|TA],TB) :- 
    pop_lists(TA,TB). 
pop_lists([[_]|TA],TB) :- 
    pop_lists(TA,TB). 

如果我們到達列表的末尾,當然我們統一用空列表過濾器,以及:

pop_list([],[]). 

我們最好把這個第一行的子句使謂詞更多方向。因此,在全面,我們有以下解決方案:

pop_list([],[]). 
pop_list([[_,H2|T]|TA],[[H2|T]|TB]) :- 
    pop_list(TA,TB). 
pop_list([[]|TA],TB) :- 
    pop_list(TA,TB). 
pop_list([[_]|TA],TB) :- 
    pop_list(TA,TB). 

我們可以進一步重新排序的語句,這樣回溯的量少:

pop_list([],[]). 
pop_list([[]|TA],TB) :- 
    pop_list(TA,TB). 
pop_list([[_]|TA],TB) :- 
    pop_list(TA,TB). 
pop_list([[_,H2|T]|TA],[[H2|T]|TB]) :- 
    pop_list(TA,TB). 
+0

謝謝,真是一個聰明而清晰的解決方案。但它返回[]和false列表,如[[1],[2]],有沒有什麼辦法可以避免這種錯誤? – Fallin

+0

@Fallin:那實際上是一樣的。 'false'只是因爲Prolog需要嘗試其他子句(以尋找其他答案)。既然失敗了,那就說錯了。所以基本上它說:「*答案是'[]',並且沒有其他答案*」 –

+0

@Fallin:通過重新排序子句,我們可以避免它:) –

相關問題