2015-11-05 138 views
2

我想從列表中刪除第一,第二,第四和第八個元素。 我該怎麼辦? 我嘗試這樣做:如何從列表中刪除序言中的第1,第2,第4和第8個元素

del([],[]). 
del([H1,H2,H3,H4|T],[H3|T]). 

和它的作品,但我怎麼能做到這一點遞歸,不寫才能刪除我想要的位置8個元素?

+1

我認爲答案取決於你想如何概括這個問題。 Jay的回答假設你想要一個完全一般的解決方案,在這個解決方案中你可以得到一個要刪除的元素的索引列表。 Paulo的解決方案對於一組固定的指數更符合實際。如果'n'是2的冪,第三個選項就是你想刪除元素'n'。第一和第三選項將使用遞歸,但第二個選項不需要它。那麼你想以什麼方式定義*我想要的職位*? – lurker

+0

這四個是你想要刪除的項目的唯一指數? – repeat

回答

0

那麼......編寫一個刪除第n個元素的謂詞,然後是一個索引列表並刪除所有這些元素?

刪除第n個很簡單:

del([_|T],T,1). 
del([Head|Tail],B,N) :- 
    K is N-1, 
    del(Tail,C,K), 
    B = [Head|C]. 

因爲我們知道,N不是1(否則會被使用的第一條),我們堅持前(看到B=[Head|C],我們沒扔Head離開!),並做一個遞歸調用del(Tail,C,K)確定C與第n個刪除。

現在,listdel,這需要索引列表:

listdelaux(A,A,[],_). 
listdelaux(A,B,Indices,Level) :- 
    Indices = [N|IndicesTail], 
    K is N-Level, 
    del(A,X,K), 
    L is Level + 1, 
    listdelaux(X,B,IndicesTail,L). 

listdel(A,B,Indices) :- listdelaux(A,B,Indices,0). 

listdelaux謂詞有四個參數:原名單,新的列表,索引列表,以及水平,這在第一個電話應該是零。 它會刪除第一個索引;然後再調用自身在新的下一個索引,調用它應該從新的指數減去被刪除已刪除的指標的數量:

[a,b,c,d,e,f]刪除[2,4]

[a,b,c,d,e,f] --> del(.,.,2) --> [a,c,d,e,f] 

[a,c,d,e,f] --> del(.,.,3) --> [a,c,e,f] 

見我們必須在第二次調用中從4中減去1。

2

統一是你的朋友:

delete_one_two_four_eight_elements(
    [_, _, Third, _, Five, Six, Seven, _| Rest], 
    [Third, Five, Six, Seven| Rest] 
). 
+0

如果我理解正確,原始海報想要一個遞歸解決方案,而不是枚舉每個第n個元素(大概是這樣可以使用不同的索引集),但我可能是錯的... – Jay

0

一般的解決方法,如果指數給出值的增加列表,也可以用DCG做:

del([C|Ns], C, Xs) --> [_], { C1 #= C + 1 }, del(Ns, C1, Xs). 
del([N|Ns], C, [X|Xs]) --> [X], { N #\= C, C1 #= C + 1 }, del([N|Ns], C1, Xs). 
del([], _, Xs) --> rest(Xs). 
del(_, _, []) --> [].  % *** 

rest([]) --> []. 
rest([X|T]) --> [X], rest(T). 

delete_indices(Indices, List, Result) :- 
    phrase(del(Indices, 1, Result), List). 

隨着第***如上所述,超出列表長度的索引被忽略:

| ?- delete_indices([1,3,5,12], [a,b,c,d,e,f,g], L). 

L = [b,d,f,g] ? ; 

no 
| ?- 

如果省略***條款,則有超過列表長度的索引的查詢會失敗,所以上面的查詢將失敗(因爲沒有12元),但與專門現有索引列表將工作:

| ?- delete_indices([1,3,5], [a,b,c,d,e,f,g], L). 

L = [b,d,f,g] ? ; 

no 
| ?- 

請注意,可以使用if_//3來實現確定性解決方案。