繁体   English   中英

一个 prolog 谓词,用于将列表拆分为每 n 个元素的单独列表

[英]A prolog predicate to split a list into sperate lists ever n elements

标题是必需的谓词,这里有几个示例查询

?- splitEvery(2,[a,b,c,d,e,f,g,h],R).

R = [[a, b], [c, d], [e, f], [g, h]] ;

false.

?- splitEvery(4,[a,b,c,d,e,f,g,h],R).

R = [[a, b, c, d], [e, f, g, h]] ;

false.

?- splitEvery(8,[a,b,c,d,e,f,g,h],R).

R = [[a, b, c, d, e, f, g, h]] ;

false.

到目前为止我的代码是这样的

splitEvery(N,List,Res):-

    splitEveryHelper1(N,List,Res,1,[]).

splitEveryHelper1(_,[],Acc,_,Acc).

splitEveryHelper1(N,[H|T],Res,C,[[H|HT]|AT]):-

    C=<N,

    C\_new is C+1,

    splitEveryHelper1(N,T,Res,C_new,[[HT]|AT]).

splitEveryHelper1(N,List,Res,C,[AH|TR]):-

    C>N,

    C\_new=1,

    splitEveryHelper1(N,List,Res,C_new,AT).

但是它不能正常工作

此紧凑片段满足您列出的查询

splitEvery(N,L,R) :-
    length(R,_),
    maplist({N}/[X]>>length(X,N),R),
    append(R,L).

但它有一个很大的缺陷(除了需要库( yall ))。 你能发现吗?

编辑

关于你的代码:你做的比要求的更复杂,忽略编译器给你的关于单例的消息。

请记住,累加器会反转列表,因此您应该删除它们。 而是在 output 参数中构建列表。

给你一个开始:

splitEvery(N,List,Res):-
    splitEveryHelper1(N,List,1,Res).

splitEveryHelper1(_,[],_,[]).
splitEveryHelper1(N,[H|T],C,[[H|R]|AT]):-
    C=<N,
    C_new is C+1,
    ....
splitEveryHelper1(N,List,C,[[]|TR]):-
    C>N,
    C_new=1,
    ....

用适当的递归调用填充点。 然后它将正常工作。

它有助于分解您的问题。 您想获取一个事物列表并将其拆分为 N 个项目的单个子列表,对吗?

这是反复执行以下操作的问题:

  • 从列表的顶部拉出不超过 N 个项目,并且
  • 递归到剩下的东西。

因此,您需要一个谓词从列表的前面提取不超过 N 个项目。 有3种情况:

  • 一般情况:N > 0 且列表非空。 在这里,我们将列表的头部添加到我们正在构建的前缀中,递减 N,然后向下递归剩下的内容。

  • 特殊情况 #1:N > 0 并且列表为空。 在这里,我们关闭前缀并返回空列表作为后缀。

  • 特殊情况 #2:N 为 0。在这里,我们关闭前缀并将源列表作为后缀返回。

first( N , [X|L] , [X|Xs] , Sfx ) :- N > 0 , N1 is N-1 , first( N1, L, Xs, Sfx ) .
first( N , []    , []     , []  ) :- N > 0 .
first( 0 , Xs    , []     , Xs  ) .

一旦我们有了它,重复调用first/4就更容易了。

  • 如果源列表为空,则列表列表为空。
  • 如果源列表非空,我们
    • 从源列表中提取前 N 个项目,并且
    • 递归到剩下的任何东西
split_every( _ , []     , []        ) .
split_every( N , [X|Xs] , [Pfx|LoL] ) :- first(N,[X|Xs],Pfx,Sfx), split_every(N,Sfx,LoL) .

你可以,错误......在这个小提琴中摆弄它: https://swish.swi-prolog.org/p/split-list.pl

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM