【问题标题】:Trying to break elements which are lists in a list?试图打破列表中的列表元素?
【发布时间】:2013-08-08 16:34:50
【问题描述】:

我正在尝试编写一个执行以下操作的程序:

?- g([2,3, [22,[3],9] ,4,[5],99],X).

X= [2,3,22,[3],9 ,4,5,99]

所以它在给定列表中搜索列表,并用不带括号 [] 的元素替换它。

所以我写了这个程序:

第一个块只搜索列表中的第一个元素,即列表
如果没有这样的元素,则返回[there_is_no_list]

first_list_in_the_list([],[there_is_no_list]):-!.  
first_list_in_the_list([H|_],X):-is_list(H),X=H,!.  
first_list_in_the_list([_|T],X):-first_list_in_the_list(T,X).

第一个块在 prolog 中完美运行。

第二个块只是在列表中搜索元素 X,然后将列表拆分为两个列表,一个是 X 之前的所有元素的列表,第二个是 X 之后的元素。

splite_when_find_element([H|T],H,[],T):-!.  
splite_when_find_element([H|T],X,F,G):-
    splite_when_find_element(T,X,F1,G),append([H],F1,F).

它在 Prolog 中也能正常工作。

第三个块是追加,它将两个列表连接在一起形成一个新列表。

append([],L,L).  
append([H|T],L,[H|U1]):- append(T,L,U1).

最后一部分是:

gg(L,L):-first_list_in_the_list(L,[there_is_no_list]),!.    
gg(L,U):-first_list_in_the_list(L,X),
         splite_when_find_element(L,X,F,G),gg(G,R),append(F,X,E),
         append(E,R,U).

当我给query [2,[3],5] 时,我也会得到[2,[3],5],我真的不明白为什么会这样。

【问题讨论】:

  • Flatten a list in Prolog的可能重复
  • 您的示例并没有删除所有子列表,但似乎只删除了中间的一个级别。例如,[1, 2, [3, [4], 5], 6] 变为 [1, 2, 3, [4], 5, 6] 如果我尝试按照您的示例进行操作。这是你想要的吗?
  • 是的,完全正确。这就是我想要的,只有一层。

标签: prolog logic dcg


【解决方案1】:

一个简单的递归解决方案也可以。递归由输入列表的头部完成。在非平凡的情况下,当头部本身是一个列表时,我们只需将扁平列表的其余部分附加到它上面。在下面的代码中,它还没有在append(H, Rest, Out) 中展平Rest,但是在递归调用g(In, Rest) 之后它会展平。在追加调用之后进行剪切确保回溯不会考虑最后一种情况,即头部将按原样出现在输出中。

% Base case, empty list.

g([], []).

% First recursive case: head is list.
% Append remaining elements to it.

g([H|In], Out):-
    append(H, Rest, Out), !,
    g(In, Rest).

% Second recursive case: head is not list.
% Will appear as-is in the output.

g([H|In], [H|Out]):-
    g(In, Out).

【讨论】:

    【解决方案2】:

    DCG 也能做到

    lev, X --> [X], {is_list(X)}, lev.
    lev, [X] --> [X], lev.
    lev --> [].
    

    测试:

    ?- phrase(lev,[a,[b,c,[d]],e],L).
    L = [a, b, c, [d], e] .
    

    【讨论】:

      【解决方案3】:

      要展平嵌套列表的 1 级,请尝试以下操作:

      flatten1( Xs , Ys ) :-        % to flatten a list
        flatten1( Xs , [] , Ys ) ,  % - invoke the worker predicate
        .                           %
      
      flatten1( [] , T , R ) :-          % if we get to to the empty list
        reverse(T,R)                     % - just reverse the accumulator and we're done.
        .                                %
      flatten1( [X|Xs] , T , R ) :-      % if the head of the list is unbound 
        var(X) ,                         % - check for being a var 
        ! ,                              % - cut (to eliminate problems on backtracking
        T1 = [X|T] ,                     % - prepend the head of the list to the accumulator
        flatten( Xs , T1 , R )           % - and recurse down
        .                                %
      flatten1( [[]|Xs] , T , R ) :-     % if head of the list is an empty list, skip it
        flatten1( Xs , T , R )           % - ignore it and recurse down
        .                                %
      flatten1( [[X|Ns]|Xs] , T , R ) :- % if head of the list is a non-empty list
        X1 = [Ns|Xs] ,                   % - prepend the tail of the sublist to the list
        T1 = [X|T] ,                     % - prepend the head of the sublist to the accumulator
        flatten( X1 , T1 , R )           % - and recurse down
        .                                %
      flatten( [X|Xs] , T , R ) :-       % if the head of the list is something else (except an unbound variable)
        T1 = [X|T] ,                     % - prepend the list head to the accumulator and
        flatten( Xs , T1 , R )           % - recurse down
        .                                %
      

      【讨论】:

        猜你喜欢
        • 2019-04-06
        • 1970-01-01
        • 1970-01-01
        • 2011-10-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-02-23
        相关资源
        最近更新 更多