Prolog如何将列表列表添加到一个列表中?

时间:2015-05-07 06:34:42

标签: list prolog append

所以我对Prolog很新,需要一些帮助。我正在尝试列出像[[1,2,3],[4,5,6],[7,8]]这样的列表,并创建一个像[2,3,5,6,8]这样的列表,所以除了每个列表的第一个之外,基本上所有值都放入一个新列表中。我明白了:

test5(X,[[_|X]|_]).
test5(X,[_|A]) :- test5(X,A).
每次按Enter键时,

会返回[2,3]然后再返回[5,6]然后返回[8]。我不确定如何让它们一次运行并将它们放入列表中。我尝试以不同的方式使用追加,但我无法使其工作。有关如何实现这一点的任何想法?谢谢!

2 个答案:

答案 0 :(得分:2)

你有一个共同的谓词flatten/2,几乎完成了这项任务:

?- flatten([[1,2,3],[4,5,6],[7,8]], L).
L = [1, 2, 3, 4, 5, 6, 7, 8].

many implementations of flatten/2 available,只是google it。

如果你知道列表列表没有嵌套,你应该使用append/2

然后,您需要在追加之前删除每个列表的第一个元素:

list_tail([_|T], T).

然后:

?- maplist(list_tail, [[1,2,3],[4,5,6],[7,8]], T), append(T, L).
T = [[2, 3], [5, 6], [8]],
L = [2, 3, 5, 6, 8].

仔细观察上面链接的append/2的实现可能是一个很好的练习。如果定义发生微小变化(字面意思是删除1个字符并添加5个字符),它将执行删除并在同一步骤中追加,而不会遍历原始列表两次。

修改

那么为什么当第一个参数不是一个正确的列表时,@repeat's initial solution不会终止,但第二个参数是一个正确的列表呢?

nt_tails_append([[_|T]|Ls], As) :-
    append(T, Ws, As),
    nt_tails_append(Ls, Ws).

这是因为当nt_tails_append/2的第一个参数是一个自由变量时,上面append/3的前两个参数也是变量。当我们在这种模式下调用append/3时,根据定义我们得到:

?- append(A, B, L).
A = [],
B = L .

换句话说,第二个和第三个参数现在是统一的。使用nt_tail_append/2的定义,这意味着递归调用获得与原始调用相同的第二个参数,并将新的自由变量作为第一个参数。当然,这是一个无限循环。

(很明显,如果你想看看上面链接的append/2的定义,你会看到第一个参数must_belist。)

这有什么帮助?

tails_append(Ls, As) :-
    maplist(list_tail, Ls, T),
    append(T, As).

list_tail([_|T], T).

定义maplist的方式,所有列表参数都将实例化为正确的列表。因此,您可以安全地使用append/3(此处,用于append/2的定义。)

答案 1 :(得分:1)

以下是使用append/3

执行此操作的方法
lists_concatenatedTails([],[]).
lists_concatenatedTails([[_|Xs0]|Xss],Ys) :-
    append(Xs0,Ys0,Ys),
    lists_concatenatedTails(Xss,Ys0).

示例查询:

?- lists_concatenatedTails([[1,2,3],[4,5,6],[7,8]], Xs).
Xs = [2, 3, 5, 6, 8].

编辑2015-05-07

请注意@Boris建议的代码(使用list_tail/2maplist/3append/2)也会为以下查询提供答案:

?- maplist(list_tail,Xss,Yss), append(Yss,[1,2,3]).
Xss = [[_G97, 1, 2, 3]],                   Yss = [[1, 2, 3]]         ;
Xss = [[_G97], [_G106, 1, 2, 3]],          Yss = [[], [1, 2, 3]]     ;
Xss = [[_G97, 1], [_G106, 2, 3]],          Yss = [[1], [2, 3]]       ;
Xss = [[_G97, 1, 2], [_G106, 3]],          Yss = [[1, 2], [3]]       ;
Xss = [[_G97, 1, 2, 3], [_G106]],          Yss = [[1, 2, 3], []]     ;
Xss = [[_G97], [_G106], [_G115, 1, 2, 3]], Yss = [[], [], [1, 2, 3]] ...

这并不是普遍终止的 - 我们也不期望它:解决方案集的大小是无限的,在这种情况下,它只能被无限的答案序列所覆盖。

在以下等效查询中lists_concatenatedTails/2"循环"马上:

?- lists_concatenatedTails(Lss,[1,2,3]).
% not a single answer within finite time

只有在立即限制Lss的长度时,才能实现公平的枚举:

?- length(Lss,_), lists_concatenatedTails(Lss,[1,2,3]).
Lss = [[_G23, 1, 2, 3]] ;
Lss = [[_G26], [_G29, 1, 2, 3]] ;
Lss = [[_G26, 1], [_G32, 2, 3]] ;
Lss = [[_G26, 1, 2], [_G35, 3]] ;
Lss = [[_G26, 1, 2, 3], [_G38]] ;
Lss = [[_G29], [_G32], [_G35, 1, 2, 3]] ...