我学习Prolog大约一个星期,所以我是一个新手。 我试图做一个附加列表元素的函数。
所以输入将是:[ [[a,b,c],[g,h,i]], [[j,k,l],[m,n,o]], [[s,t,u],[v,w,x]] ].
输出结果为:[ [a,b,c,j,k,l,s,t,u], [g,h,i,m,n,o,v,w,x] ].
或者
输入:[ [[a,b], [c,d]], [[e,f], [g,h]], [[i,j],[k,l]] ].
输出:[ [a,b,e,f,i,j], [c,d,g,h,k,l] ].
重要的是,它必须与许多元素一起工作,而不仅仅是3。 我写了这个,但它只适用于2个元素,所以我只能用它来做。
merge([],[],[]).
merge(L1,[],L1).
merge([H1|T1],[H2|T2],LL):-
append(H1, H2, HE),
merge(T1,T2,TE),
append([HE], TE, LL).
答案 0 :(得分:1)
如果我理解你的问题......
首先,如果您知道您的输入中只有两个嵌套级别,并且如果您的Prolog具有用于映射和折叠的高阶谓词,并且如果您可以编写它们,则可以简单地写:
merge_foldl([], []).
merge_foldl([X|Xs], R) :-
reverse([X|Xs], [Y|Ys]),
foldl(maplist(append), Ys, Y, R).
这与SWI-Prolog的预期一致。 这是你的两个例子:
?- merge_foldl([ [[a,b,c],[g,h,i]], [[j,k,l],[m,n,o]], [[s,t,u],[v,w,x]] ], R).
R = [[a, b, c, j, k, l, s, t, u], [g, h, i, m, n, o, v, w, x]].
?- merge_foldl([ [[a,b], [c,d], [e,f]], [[g,h], [i,j], [k,l]] ], R).
R = [[a, b, g, h], [c, d, i, j], [e, f, k, l]].
如果您无法访问foldr
或foldl
,则必须对折叠进行硬编码:
merge([], []).
merge([X|Xs], Result) :-
merge_maplist(Xs, X, Result).
merge_maplist([], Result, Result).
这不是全部,但它表示,如果您位于列表列表的末尾,则最后一个元素就是结果。
现在,您必须定义附加到每个子列表前面的步骤。使用maplist
:
merge_maplist([X|Xs], Prev, Result) :-
merge_maplist(Xs, X, Result0),
maplist(append, Prev, Result0, Result).
请注意,我们在这里"仿效"通过使用非尾递归定义进行右折叠:在递归步骤之后,我们正在反向执行追加。对于尾递归定义(与硬编码左折叠相同),您必须首先反转原始列表!
所以你继续从输入中删除一个列表列表,直到完成为止。然后,使用maplist
将append/3
应用于前一个元素的每对列表和到目前为止的结果,以获得最终结果。
如果您无法访问maplist
,您也必须对映射进行硬编码。对于append/3
采用的三个参数:
map_append([], [], []).
map_append([X|Xs], [Y|Ys], [Z|Zs]) :-
append(X, Y, Z),
map_append(Xs, Ys, Zs).
,您的merge/2
和merge_/3
成为:
merge([], []).
merge([X|Xs], Result) :-
merge_(Xs, X, Result).
merge_([], Result, Result).
merge_([X|Xs], Prev, Result) :-
merge_(Xs, X, Result0),
map_append(Prev, Result0, Result).
如果您有更高阶的谓词,这是很多可以很好解决的代码。