List PROLOG-展平段列表

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). 但它给了我以下输出:

我想将列表展平如下:

[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).
但它给了我以下输出:

?- 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 ? ;
.
.
.