例如:
createlistoflists([1,2,3,4,5,6,7,8,9], NewLists)
NewLists = [[1,2,3], [4,5,6], [7,8,9].
所以基本上我的第一个参数是一个列表,我的第二个参数是一个新列表,其中包含具有适当长度的列表(适当的长度为3)。我的第一个想法是使用某种附加物。但我真的不知道怎么做,有什么想法吗?
提前致谢
答案 0 :(得分:4)
如果你不介意使用Prolog为你提供的漂亮设施,那就有一个简单的方法;
list_length(Size, List) :- length(List, Size).
split_list(List, SubSize, SubLists) :-
maplist(list_length(SubSize), SubLists),
append(SubLists, List).
您可以将其查询为:
?- split_list([1,2,3,4,5,6,7,8,9], 3, L).
L = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
如果List
以长度不是SubSize
的倍数的方式实例化,则会失败。
maplist(list_length(SubSize), SubList)
将继续查询并查找更长和更长的子列表集,不受约束。因此,在重试时,上面的查询不会终止。
诱惑就是使用这样的剪辑:
split_list(List, SubSize, SubLists) :-
maplist(list_length(SubSize), SubLists), !,
append(SubLists, List).
这里的剪辑假设您只想获得一个答案,就好像您正在编写命令功能一样。
更好的方法是尝试以合理的方式将SubList
参数约束到maplist
。一个简单的方法是确保SubList
的长度不超过List
的长度,因为从逻辑上讲,它应该永远不会更大。添加此约束:
list_length(Size, List) :- length(List, Size).
not_longer_than([], []).
not_longer_than([], [_|_]).
not_longer_than([_|X], [_|Y]) :-
not_longer_than(X, Y).
split_list(List, SubSize, SubLists) :-
not_longer_than(SubLists, List),
maplist(list_length(SubSize), SubLists),
append(SubLists, List).
然后查询终止而不会失去解决方案的一般性:
?- split_list([1,2,3,4,5,6,7,8,9], 3, L).
L = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] ;
false.
?-
在not_longer_than/2
的实施中,可以更准确地使用SubSize
作为倍数。这样会更有效但不需要终止。
not_longer_than_multiple(L1, Mult, L2) :-
not_longer_than_multiple(L1, Mult, Mult, L2).
not_longer_than_multiple([], _, _, []).
not_longer_than_multiple([], _, _, [_|_]).
not_longer_than_multiple([_|Xs], Mult, 1, [_|Ys]) :-
not_longer_than_multiple(Xs, Mult, Mult, Ys).
not_longer_than_multiple(Xs, Mult, C, [_|Ys]) :-
C #> 1,
C1 #= C - 1,
not_longer_than_multiple(Xs, Mult, C1, Ys).
或者沿着那些方向......
<小时/> 但是,如果我们要经历所有那些无意义的事情来掩盖maplist
这种使用的罪行,那么正面碰到这个问题就可以得到最清晰的解决方案:
split_list(List, SubSize, SubLists) :-
split_list(List, SubSize, SubSize, SubLists).
split_list([], _, _, []).
split_list([X|Xs], SubList, 1, [[X]|S]) :-
split_list(Xs, SubList, SubList, S).
split_list([X|Xs], SubSize, C, [[X|T]|S]) :-
C #> 1,
C1 #= C - 1,
split_list(Xs, SubSize, C1, [T|S]).