[英]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 個項目。 有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
就更容易了。
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.