如何从列表中删除Prolog中的第1,第2,第4和第8个元素

时间:2015-11-05 09:15:13

标签: list prolog

我想从列表中删除第一,第二,第四和第八个元素。 我能怎么做? 我试过这个:

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

它有效,但我怎么能递归地做,而不是写8个元素来删除我想要的位置?

3 个答案:

答案 0 :(得分:3)

统一是你的朋友:

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

答案 1 :(得分:1)

一般解决方案,如果索引是作为增加的值列表给出的,也可以使用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可以实现确定性解决方案。

答案 2 :(得分: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谓词有四个参数:原始列表,新列表,索引列表和级别,它们在第一次调用中应为零。 它将删除第一个索引;然后再次调用自己的下一个索引,但是在新的调用中它应该从新索引中减去要删除的已删除索引的数量:

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

[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。