Prolog新手求教:如何按指定规则重排多列表结构?
在Prolog中实现列表的批量拆分与重组
你的需求完全可以在Prolog中实现,先来看针对你例子的解决方案,再分析你原有代码的问题。
解决方案代码
我们可以通过递归+批量处理的方式实现目标:
基础拆分谓词(可复用)
% 从单个列表中提取前K个元素,返回前K个元素和剩余部分 get_first_k(List, K, FirstK, Remainder) :- length(FirstK, K), append(FirstK, Remainder, List).
批量收集每个子列表的前K个元素
% 从列表的列表中,为每个子列表提取前K个元素,返回所有前K元素的列表,以及剩余子列表的列表 collect_first_ks([], _, [], []). collect_first_ks([List|Rest], K, [FirstK|FirstKs], [Remainder|Remainders]) :- get_first_k(List, K, FirstK, Remainder), collect_first_ks(Rest, K, FirstKs, Remainders).
主谓词:实现批量重组
% 把原列表的列表按规则重组为目标列表的列表 batch_split([], _, []). batch_split(OriginalLists, K, [Combined|ResultRest]) :- % 终止条件:所有子列表都为空时停止 OriginalLists \= [[]|_], % 收集所有子列表的前K个元素,以及剩余部分 collect_first_ks(OriginalLists, K, FirstKs, Remainders), % 将所有前K元素的列表拼接成一个大列表 append(FirstKs, Combined), % 递归处理剩余的子列表 batch_split(Remainders, K, ResultRest).
测试你的例子
调用方式如下:
Original = [ [1,2,3,4,5,6,7,8,9,10,11,12], [13,14,15,16,17,18,19,20,21,22,23,24], [25,26,27,28,29,30,31,32,33,34,35,36] ], batch_split(Original, 4, Result).
执行后Result会得到你期望的输出:
[ [1,2,3,4,13,14,15,16,25,26,27,28], [5,6,7,8,17,18,19,20,29,30,31,32], [9,10,11,12,21,22,23,24,33,34,35,36] ]
你原有代码的问题分析
你得到false的核心原因有两个:
- 谓词名大小写错误:Prolog中谓词必须以小写字母开头,你定义的
GetLists首字母大写,会被Prolog当作原子而非谓词,调用时自然找不到对应的规则,返回false。 - 递归逻辑不完整:你的代码只处理了一次所有子列表的前K元素,没有循环处理剩余部分,也没有将多个前K元素列表拼接成一个大列表,无法生成多批次的目标列表。
简化版本(基于SWI-Prolog内置谓词)
如果使用SWI-Prolog,可以利用内置的split_at/3和maplist/3简化代码,无需自己实现get_first_k和collect_first_ks:
batch_split(OriginalLists, K, ResultLists) :- ( OriginalLists = [[]|_] -> ResultLists = [] ; maplist(split_at(K), OriginalLists, FirstKs, Remainders), append(FirstKs, Combined), ResultLists = [Combined|Rest], batch_split(Remainders, K, Rest) ).
内容的提问来源于stack exchange,提问作者Lyon Garilthane Kylcor
相关产品推荐
相关产品推荐

