2015-11-05 133 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来实现确定性解决方案。