Prolog:如何删除列表中的每个第二个元素

时间:2011-05-09 09:44:25

标签: list prolog

我需要在Prolog中编写一个应该删除列表中每个第二个元素的程序。应该这样工作:[1,2,3,4,5,6,7] - > [1,3,5,7]

到目前为止我有这个,但它只是返回“false”。

r([], []). 
r([H|[T1|T]], R) :- del(T1,[H[T1|T]], R), r(R).

del(X,[X|L],L).
del(X,[Y|L],[Y|L1]):- del(X,L,L1).

5 个答案:

答案 0 :(得分:7)

这是Landei在特定Prolog语法中的答案:

r([], []).
r([X], [X]).
r([X,_|Xs], [X|Ys]) :- r(Xs, Ys).

第二个谓词不是必需的。

答案 1 :(得分:4)

使用foldl/4的替代解决方案:

fold_step(Item, true:[Item|Tail], false:Tail).
fold_step(_Item, false:Tail, true:Tail).

odd(List, Odd) :-
    foldl(fold_step, List, true:Odd, _:[]).

用法:

?- odd([1, 2, 3, 4, 5, 6, 7], Odd).
Odd = [1, 3, 5, 7]

这个想法是通过列表,同时保持“奇数/偶数”标志并在每个元素上翻转其值(false - > true,true - > false)。我们还逐步构建列表,方法是将那些“奇/偶”标志等于true的元素附加到其他元素上。

答案 2 :(得分:3)

This fine answer by @code_x386使用foldl/4

我们只使用一个fold_step/3子句使关系更加通用,如下所示:

fold_step(X, [X|Xs]+Ys, Ys+Xs).

list_odds_evens(List, Odds, Evens) :-
   foldl(fold_step, List, Odds+Evens, []+[]).

示例查询:

?– list_odds_evens([a,b,c,d,e,f], Odds, Evens).
Evens = [b,d,f], Odds = [a,c,e]
?– list_odds_evens([a,b,c,d,e,f,g], Odds, Evens).
Evens = [b,d,f], Odds = [a,c,e,g]

修改

为什么不使用一个较少的子句并取消谓词fold_step/3救援!

:- use_module(library(lambda)).

list_odds_evens(List, Odds, Evens) :-
   foldl(\X^([X|Xs]+Ys)^(Ys+Xs)^true, List, Odds+Evens, []+[]).

答案 3 :(得分:2)

另一种可能性是使用DCG,在描述列表时通常是值得考虑的因素:

list_oddindices(L,O) :-
   phrase(oddindices(L),O).  % the list O is described by oddindices//1

oddindices([]) -->           % if L is empty
   [].                       % O is empty as well
oddindices([X]) -->          % if L has just one element
   [X].                      % it's in O
oddindices([O,_E|OEs]) -->   % if L's head consists of at least two elements
   [O],                      % the first is in O
   oddindices(OEs).          % the same holds for the tail

这肯定不如使用foldl / 4的解决方案优雅,但代码非常容易阅读,但它解决了OP描述的任务,并且同时也是两种方式:

?- list_oddindices([1,2,3,4,5,6,7],O).
O = [1, 3, 5, 7] ;
false.

?- list_oddindices(L,[1,3,5,7]).
L = [1, _G4412, 3, _G4418, 5, _G4424, 7] ;
L = [1, _G4412, 3, _G4418, 5, _G4424, 7, _G4430] ;
false.

答案 4 :(得分:0)

我这里没有Prolog可以尝试一下,而且我有点生疏,但它应该是

r([]) :- [].
r([X]) :- [X].
r([X,Y|Z]) :- R=r(Z),[X|R].

<强> [编辑]

当然垫是对的。我的解决方案适用于Haskell或Erlang等函数式语言:

--Haskell
r [] = []
r [x] = [x]
r (x:_:xs) = x : (r xs)

在Prolog中,您必须将右侧“拉”到参数列表中才能触发统一。