扁平化列表

时间:2012-06-27 06:28:12

标签: prolog dcg

我需要编写一个平面列表的函数。

例如:

flat([ c , [[[]]] , [] , k] , X).
X=[c,k]

这就是我所做的:

    flat([],[]).
    flat([[A] |B] , R) :- flat([A|B],R).
    flat([[]|L],L1) :- flat(L,L1).!
    flat([[A|L]|W],R) :- flat([A|L],U), flat(W,W1), append(U,W1,R).
    flat([A|L], [A|L1]) :- flat(L,L1).

我知道为什么不是这样,但我不知道该怎么做。 感谢。

修改 几乎工作:

    flat([],[]).
flat([[]|L],L1) :- flat(L,L1).  --- i think something here missing
flat([[A|L]|W],R) :- flat([A|L],U), flat(W,W1), append(U,W1,R).
flat([A|L], [A|L1]) :- flat(L,L1).


?- flat([c , [[[]]] , [] , k],C).
C = [c, k] ;
C = [c, [], k] ;
C = [c, [], k] ;
C = [c, [], [], k] ;
C = [c, [[]], k] ;
C = [c, [[]], [], k] ;
C = [c, [[[]]], k] ;
C = [c, [[[]]], [], k].

3 个答案:

答案 0 :(得分:1)

flatten(List, FlatList) :-
    flatten(List, [], FlatList0), !,
    FlatList = FlatList0.

flatten(Var, Tl, [Var|Tl]) :-
    var(Var), !.
flatten([], Tl, Tl) :- !.
flatten([Hd|Tl], Tail, List) :- !,
    flatten(Hd, FlatHeadTail, List),
    flatten(Tl, Tail, FlatHeadTail).
flatten(NonList, Tl, [NonList|Tl]).

以下是Jan Wielemaker和Richard O'Keefe的swi-prolog解决方案, 代码可以在prolog的库目录中找到,在lists.pl文件中。

答案 1 :(得分:1)

编辑的代码(见评论)

使用DCG的另一种可能性:

flat(L, FL) :-
    flat(L, FL, []).

flat(X) -->
    {var(X)},
    !,
    [X].

flat([]) --> 
    [], 
    !.

flat([X | T]) -->
    flat(X),
    !,
    flat(T).

flat(X) --> [X].

现在我们得到:

 ?- flat([[a,b,c,d|r]], FL) .
FL = [a,b,c,d,r] .


 ?- flat([1,2,[3,4]],L).
L = [1,2,3,4] .

 ?- flat([1,2,[3,4]],[1,2,3,4]).
true .

 ?- flat([ c , [[[]]] , [] , k] , X).
X = [c,k] .

答案 2 :(得分:0)

那爆炸(......平(L,L1)。!...)这是一个错字,不是吗?

你可以从SWI-Prolog学习一个good implementation,它会公开它的代码并给出预期的结果:

?- flatten([ c , [[[]]] , [] , k] , X).
X = [c, k].

否则,尝试使用简单的案例进行调试,以查看代码在清理后失败的位置。 顺便说一下,你的代码似乎有用,只需产生更多的解决方案,你需要修剪一些不需要的路径:

?- flat([c , [[[]]] , [] , k],C).
C = [c, k] ;
C = [c, [], k] ;
C = [c, [], k] ;
C = [c, [], [], k] .
...

编辑这里是来自SWI-Prolog

的库(列表)的代码
%%  flatten(+List1, ?List2) is det.
%
%   Is true if List2 is a non-nested version of List1.
%
%   @deprecated Ending up needing flatten/3 often indicates,
%           like append/3 for appending two lists, a bad
%           design.  Efficient code that generates lists
%           from generated small lists must use difference
%           lists, often possible through grammar rules for
%           optimal readability.
%   @see append/2

flatten(List, FlatList) :-
    flatten(List, [], FlatList0), !,
    FlatList = FlatList0.

flatten(Var, Tl, [Var|Tl]) :-
    var(Var), !.
flatten([], Tl, Tl) :- !.
flatten([Hd|Tl], Tail, List) :- !,
    flatten(Hd, FlatHeadTail, List),
    flatten(Tl, Tail, FlatHeadTail).
flatten(NonList, Tl, [NonList|Tl]).

您的代码似乎相当正确WRT您的评论:

?- flat([1,2,[3,4]],[1,2,3,4]).
true ;
false.