фильтровать список в отдельные списки

Мне нужно отфильтровать список [#,d,e,#,f,g] таким образом, чтобы я получал вывод как [[d,e],[f,g]] ,
Я застреваю при создании нового списка каждый раз, когда встречаю '#'. Есть ли способ сделать это? Я попробовал код ниже,

filterL([],List) :-[].
filterL([Head|Tail],X) :-
   (  Head \='#'->
      append(X,Head,List),
      filterL(Tail,List)
   ;  filterL(Tail,X)
   ).

person sand    schedule 18.10.2014    source источник
comment
% — это комментарий, поэтому используйте кавычки, например ['%',d,e,'%',f,g].   -  person false    schedule 18.10.2014
comment
... а то не понятно, что значит ваша программа. List в первом предложении не имеет никакого смысла. Вероятно, вам нужен предикат арности 3, а не 2. В Прологе нет операторов возврата.   -  person false    schedule 18.10.2014
comment
@false он должен просто вернуть пустой список.   -  person sand    schedule 18.10.2014
comment
Итак, [], [#], [#,#], [#,#,#]... все дают []?   -  person false    schedule 18.10.2014
comment
@false да, если ввод [#,a,b,#,#,c,d], то он должен дать [[a,b],[c,d]].   -  person sand    schedule 18.10.2014


Ответы (3)


Ваша проблема не очень четко определена. Разрешены ли пустые последовательности или нет? Должен ли [#] быть связан с [[],[]] (есть пустая последовательность до и после) или []? Вы говорите, что это должно быть []. Так:

list_splitbyhash(Xs, Xss) :-
   phrase(splitby(Xss,#), Xs).

splitby([],_E) -->
    [].
splitby(Xss,E) -->
    [E],
    splitby(Xss,E).
splitby([Xs|Xss],E) -->
    {Xs = [_|_]},
    all_seq(dif(E),Xs),
    splitby(Xss,E).

all_seq(_, []) --> [].
all_seq(C_1, [C|Cs]) -->
   [C],
   {call(C_1,C)},
   all_seq(C_1, Cs).
person false    schedule 18.10.2014

Вот еще одна версия, в которой используется еще более общий подход:

list_splitbyhash(Xs, Xss) :-
   phrase(by_split(=(#), Xss), Xs).

=(X,X,true).
=(X,Y,false) :- dif(X,Y).

by_split(_C_2, []) --> [].
by_split(C_2, Xss) -->
   [E],
   {call(C_2,E,T)},
   (  { T = true },
      by_split(C_2, Xss)
   |  { T = false, Xss = [[E|Xs]|Xss1] },
      all_seq(callfalse(C_2),Xs),
      el_or_nothing(C_2),
      by_split(C_2, Xss1)
   ).

callfalse(C_2,E) :-
   call(C_2,E,false).

el_or_nothing(_) -->
   call(nil).
el_or_nothing(C_2), [E] -->
   [E],
   {call(C_2,E,true)}.

nil([], []).

С помощью лямбда-выражений это можно выразить более компактно. Вместо

   all_seq(callfalse(C_2),Xs)

и определение для callfalse/3 теперь можно написать

   all_seq(C_2+\F^call(C_2,F,false))
person false    schedule 18.10.2014
comment
Можно ли получить только одно решение из числа решений, выдаваемых предикатом пролога? Например, list_splitbyhash([#,1,2,3,#],X). дает только [[1,2,3]]. - person sand; 18.10.2014
comment
Ты прав! Исправлено, даже если это уже не так хорошо, как раньше. - person false; 18.10.2014
comment
Спасибо, мне просто было интересно. - person sand; 18.10.2014
comment
list_splitbyhash([k,#,l,m,#,#,N],X). дает, X = [[k], [l, m], [N]], dif(N, #). Можно ли игнорировать «dif(N,#)» на выходе? - person sand; 19.10.2014
comment
@sand: Это было бы неправильно! Кроме того, пожалуйста, посмотрите на разные ответы, потому что их много! - person false; 19.10.2014
comment
Что, если мне нужен только последний вывод? Есть ли способ получить его без других? Например, [A,#,B] мне нужно '[[A],[B]]'. - person user3928256; 24.10.2014

С метапредикатом splitlistIf/3 и материализованным предикатом равенства (=)/3, выполняемая задача становится однострочной --- эффективной и логически чистой!

?- splitlistIf(=(#),[#,d,e,#,f,g],Xs).
Xs = [[d,e],[f,g]].                      % succeeds deterministically

Так как код монотонный, логическая корректность обеспечивается даже для довольно общих запросов:

?- Xs = [A,B,C], splitlistIf(=(X),Xs,Yss).
Xs = [A,B,C],     X=A ,     X=B ,     X=C , Yss = [       ] ;
Xs = [A,B,C],     X=A ,     X=B , dif(X,C), Yss = [    [C]] ;
Xs = [A,B,C],     X=A , dif(X,B),     X=C , Yss = [  [B]  ] ;
Xs = [A,B,C],     X=A , dif(X,B), dif(X,C), Yss = [  [B,C]] ;
Xs = [A,B,C], dif(X,A),     X=B ,     X=C , Yss = [[A]    ] ;
Xs = [A,B,C], dif(X,A),     X=B , dif(X,C), Yss = [[A],[C]] ;
Xs = [A,B,C], dif(X,A), dif(X,B),     X=C , Yss = [[A,B]  ] ;
Xs = [A,B,C], dif(X,A), dif(X,B), dif(X,C), Yss = [[A,B,C]].
person repeat    schedule 15.05.2015