【问题标题】:filter list into separate lists将列表过滤到单独的列表中
【发布时间】:2014-10-18 11:04:43
【问题描述】:

我需要过滤列表 [#,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)
   ).

【问题讨论】:

  • % 是注释,因此请使用 ['%',d,e,'%',f,g] 之类的引号
  • ... 否则不清楚你的程序是什么意思。第一个子句中的List 没有任何意义。您可能想要一个 arity 3 而不是 2 的谓词。Prolog 中没有 return 语句。
  • @false 它应该只返回一个空列表。
  • 所以[], [#], [#,#], [#,#,#] ...都给[]?
  • @false 是的,如果输入是[#,a,b,#,#,c,d] 那么它应该给出[[a,b],[c,d]]。跨度>

标签: list prolog prolog-dif


【解决方案1】:

您的问题没有很好地定义。是否允许空序列? [#]应该与[[],[]]相关(前后有一个空序列)还是[]?你说应该是[]。所以:

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).

【讨论】:

    【解决方案2】:

    这是另一个版本,它使用了更通用的方法:

    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([], []).
    

    使用lambdas,可以更简洁地表达。而不是

       all_seq(callfalse(C_2),Xs)
    

    还有callfalse/3的定义,现在可以写了

       all_seq(C_2+\F^call(C_2,F,false))
    

    【讨论】:

    • 是否有可能从prolog谓词产生的解的数量中只得到一个解?例如,list_splitbyhash([#,1,2,3,#],X)。只给出 [[1,2,3]]。
    • 你是对的!已修复,即使这不再像以前那样好。
    • 谢谢,我只是好奇。
    • list_splitbyhash([k,#,l,m,#,#,N],X)。给出,X = [[k], [l, m], [N]], dif(N, #)., 是否可以从输出中忽略 'dif(N,#)'?
    • @sand:那是不正确的!另外,请看不同的答案,因为有很多!
    【解决方案3】:

    使用元谓词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]].
    

    【讨论】:

      猜你喜欢
      • 2020-01-03
      • 2016-03-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-26
      • 1970-01-01
      相关资源
      最近更新 更多