【发布时间】:2022-10-05 03:56:59
【问题描述】:
我正在 SWI-Prolog 中寻找一些谓词来获取一些任意嵌套列表的元素。意味着,如果我例如有清单:
L = [[a,b], c, [d, [e, f]]]
我得到结果:
R = [a,b,c,d,e,f]
-
使用 flatten/2 - swi-prolog.org/pldoc/man?predicate=flatten/2
标签: list nested prolog swi-prolog
我正在 SWI-Prolog 中寻找一些谓词来获取一些任意嵌套列表的元素。意味着,如果我例如有清单:
L = [[a,b], c, [d, [e, f]]]
我得到结果:
R = [a,b,c,d,e,f]
标签: list nested prolog swi-prolog
SWI 内置谓词flatten/2 取决于第一个参数的实例化。因此,它会导致完全不相关的行为:
?- flatten(X,[]).
false.
?- X = [], flatten(X,[]).
X = [].
?- X = [[],[]], flatten(X,[]).
X = [[], []].
?- X = [[]|[]], flatten(X,[]).
X = [[]].
请注意,有无限多个X 可以使flatten(X,[]) 成功。如果您希望这是一个关系,则有两种选择,要么枚举所有此类解决方案,要么产生实例化错误,要么不终止(比不正确的答案更好),或者适当地延迟目标,或者产生一些约束,或者产生资源错误。哦,现在已经有 6 个选项了... ...以免我忘记,您也可以组合这些选项,例如首先生成一些答案替换,然后延迟目标,然后是约束,然后循环相当长的时间以最终生成一个资源错误。
在大多数此类情况下,最简单的方法是产生如下实例化错误:
flattened(T) -->
{functor(T,_,_)}, % ensures instantiation
( {T = [E|Es]} -> flattened(E), flattened(Es)
; {T = []} -> []
; [T]
).
?- phrase(flattened([[]|[]]),Xs).
Xs = [].
?- phrase(flattened([[]|_]),Xs).
error(instantiation_error,functor/3).
【讨论】:
正如@brebs 在他的评论中提到的,使用预定义谓词flatten/2
% ?- flatten([[a,b], c, [d, [e, f]]], R).
% R = [a, b, c, d, e, f]
这种用户定义的实现类似于预定义的实现[1]
my_flatten([],[]).
my_flatten([H|T], [H|Res]) :- \+ is_list(H), my_flatten(T, Res), !.
my_flatten([H|T], Res) :- my_flatten(H, Res). % H is list.
[1]除了my_flatten(X,non_list) 等非终止的情况。和喜欢my_flatten([X],[1,2,3,4])。感谢@false 评论
【讨论】:
my_flatten(X,non_list).这样的不终止的情况和像my_flatten([X],[1,2,3,4]).这样的缺乏坚定性的情况
my_flatten([[a|b]],Xs).
这是使用底部描述的谓词获得的结果。
% Lis= [[e1, e2, [e31, e32]], [e4, e5, e6, e7], [e8, e9]],
% flat_lvl(Lis, FlatLis, 2).
%
% ---> FlatLis = [e1, e2, e3, e4, e5, e6, e7, e8, e9]
% Lis= [[e1, e2, [e31, e32]], [e4, e5, e6, e7], [e8, e9]],
% flat_lvl(Lis, FlatLis, 1).
%
% ---> FlatLis = [e1, e2, [e31, e32], e4, e5, e6, e7, e8, e9]
% Lis= [[e1, e2, [e31, e32]], [e4, e5, e6, e7], [e8, e9]],
% flat_lvl(Lis, FlatLis, 0).
%
% ---> FlatLis = [[e1, e2, [e31, e32]], [e4, e5, e6, e7], [e8, e9]]
将具有指定级别的列表展平的谓词如下:
flat_lvl([],[],_).
flat_lvl([LisH| LisT], FlatLis, DeepLvl):-
Lvl is DeepLvl - 1, Lvl >= -1,
(flat_lvl(LisH, FlatH, Lvl); FlatH= [LisH]),
flat_lvl(LisT, FlatTail, DeepLvl),
append(FlatH, FlatTail, FlatLis), !.
【讨论】: