List PROLOG-展平段列表
我想将列表展平如下: [a,b],[b,c],[c,d],…]->[a,b,c.] 简而言之,我想取每个段[a,b]的头部,并将其放在一个展开的列表中 我有当前代码:List PROLOG-展平段列表,list,prolog,List,Prolog,我想将列表展平如下: [a,b],[b,c],[c,d],…]->[a,b,c.] 简而言之,我想取每个段[a,b]的头部,并将其放在一个展开的列表中 我有当前代码: %unsplits a list from segments %e.g [[a,b],[b,c]] becomes [a,b,c]. unSplitList([],_). unSplitList([[H,_]|T], L) :- append([H], L1, L), unSplitList(T, L1). 但它给了我以下输出:
%unsplits a list from segments
%e.g [[a,b],[b,c]] becomes [a,b,c].
unSplitList([],_).
unSplitList([[H,_]|T], L) :- append([H], L1, L), unSplitList(T, L1).
但它给了我以下输出:
?- unSplitList([[a,b],[b,c],[c,d]],L).
L = [a, b, c|_1046].
我该如何继续去掉那条尾巴呢?提前感谢:)。这里的问题是下面的下划线:
unSplitList([],_).
这意味着“动态”构建的列表不会以[]
结尾,因此保持开放的结尾
您可以通过以下方式解决此问题:
unSplitList([], []).
我们还可以通过以下方式改进上述内容:
请注意,上述方法不适用于包含空子列表(或数字等其他对象)的列表。除了@WillemVanOnsem基于maplist/3的优雅解决方案之外,我想指出使用DCG描述头部列表的可能性
lists_heads(Ls,Hs) :- % the list of heads, HS, of the lists in Ls
phrase(heads(Ls),Hs). % is described by the DCG heads//1
heads([]) --> % if there are no lists
[]. % there are no heads
heads([L|Ls]) --> % if L is the first list in the list of lists
head(L), % its head is in the list of heads
heads(Ls). % followed by the heads of the other lists
head([H|_]) --> % the head H of the list
[H]. % is in the list of heads
此DCG版本生成的答案与Willem基于maplist/3的版本相同:
?- lists_heads([[a,b],[b,c],[c,d]],L).
L = [a,b,c]
?- unSplitList([[a,b],[b,c],[c,d]],L).
L = [a,b,c]
?- lists_heads([[a,b,c],[b,c],[c,d]],L).
L = [a,b,c]
?- unSplitList([[a,b,c],[b,c],[c,d]],L).
L = [a,b,c]
?- lists_heads(Ls,[a,b,c]).
Ls = [[a|_A],[b|_B],[c|_C]] ? ;
no
?- unSplitList(Ls,[a,b,c]).
Ls = [[a|_A],[b|_B],[c|_C]]
正如Willem还指出的,只有在第一个参数不包含空列表的情况下,这些谓词才会起作用。您可以很容易地修改DCG head//1以考虑此类情况。出于比较原因,我将修改后的版本命名为2/2,仅对附加的DCG规则进行注释:
lists_heads2(Ls,Hs) :-
phrase(heads2(Ls),Hs).
heads2([]) -->
[].
heads2([L|Ls]) -->
head2(L),
heads2(Ls).
head2([]) --> % if the list is empty
[]. % it contributes no element to the list of heads
head2([H|_]) -->
[H].
以下查询说明了两个版本之间的差异:
?- lists_heads([[],[a,b,c],[],[b,c],[c,d]],L).
no
?- lists_heads2([[],[a,b,c],[],[b,c],[c,d]],L).
L = [a,b,c]
但是,这种额外的灵活性带来的代价乍看起来可能并不明显:因为第一个参数可以包含任意数量的空列表,如果在另一个方向使用,列表2/2将循环:
?- lists_heads(Ls,[a,b,c]).
Ls = [[a|_A],[b|_B],[c|_C]] ? ;
no
?- lists_heads2(Ls,[a,b,c]).
... % <- loops infinitely
?- length(Ls,N), lists_heads2(Ls,[a,b,c]).
Ls = [[a|_A],[b|_B],[c|_C]], % solution of length 3
N = 3 ? ;
Ls = [[],[a|_A],[b|_B],[c|_C]], % solutions of length 4
N = 4 ? ;
Ls = [[a|_A],[],[b|_B],[c|_C]],
N = 4 ? ;
Ls = [[a|_A],[b|_B],[],[c|_C]],
N = 4 ? ;
Ls = [[a|_A],[b|_B],[c|_C],[]],
N = 4 ? ;
Ls = [[],[],[a|_A],[b|_B],[c|_C]], % solutions of length 5
N = 5 ? ;
.
.
.
提示:为什么要在
取消列表([],)中写入。
?另一个相关提示:取消列表([],))。
说。
(任何内容)都是取消列表的结果。这看起来合乎逻辑吗?换句话说,例如,unSplitList([],foo(x,56))
是真的<代码>\uu
是一个匿名变量。
?- lists_heads(Ls,[a,b,c]).
Ls = [[a|_A],[b|_B],[c|_C]] ? ;
no
?- lists_heads2(Ls,[a,b,c]).
... % <- loops infinitely
?- length(Ls,N), lists_heads2(Ls,[a,b,c]).
Ls = [[a|_A],[b|_B],[c|_C]], % solution of length 3
N = 3 ? ;
Ls = [[],[a|_A],[b|_B],[c|_C]], % solutions of length 4
N = 4 ? ;
Ls = [[a|_A],[],[b|_B],[c|_C]],
N = 4 ? ;
Ls = [[a|_A],[b|_B],[],[c|_C]],
N = 4 ? ;
Ls = [[a|_A],[b|_B],[c|_C],[]],
N = 4 ? ;
Ls = [[],[],[a|_A],[b|_B],[c|_C]], % solutions of length 5
N = 5 ? ;
.
.
.