如何将元素附加到Prolog中的列表中?

时间:2013-02-22 16:30:59

标签: list prolog append in-place difference-lists

如果我在Prolog中有一个列表,例如X = [1,2,3,4],我如何将元素5添加到列表末尾以使X = [1,2,3,4, 5]

append函数需要两个列表,即追加(A,B,C)以获得A和B连接到列表C.

我可以用临时列表Y = [1,2,3,4]和Z = [5]来做这个,然后做一个追加(Y,Z,X),但我不喜欢有一个临时名单。

通常的免责声明适用于此 - 这不是家庭作业,我只是在学习Prolog。

6 个答案:

答案 0 :(得分:7)

正如其他人所指出的那样,你将会遇到性能问题 但就像练习一样,我决定尝试创建一个谓词,可以将一个元素附加到列表的末尾,而不使用append

% add_tail(+List,+Element,-List)
% Add the given element to the end of the list, without using the "append" predicate.
add_tail([],X,[X]).
add_tail([H|T],X,[H|L]):-add_tail(T,X,L).

我建议您只使用append函数,作为内置函数,它可能比手动制作的任何函数都快。

答案 1 :(得分:6)

Prolog中的变量只能分配一次。只要X具有值[1,2,3,4],它就永远不会有另一个值。像你提到的那样,临时变量和附加/ 3就是这样做的方法。

话虽如此,你可以做一个可能不推荐的技巧。如果X = [1,2,3,4,Y]那么你可以做Y = 5而X现在有你想要的值。我相信这种技术被称为差异列表。

答案 2 :(得分:3)

一个声明性解决方案是使用差异列表(正如Daniel在其答案中所建议的那样)。差异列表的名称通常表示为两个列表之间的差异:列表及其尾部。例如,空列表可以表示为T-T。包含元素1,2和3的列表可以表示为[1,2,3| T]-T(请注意(-)/2是标准的内置中缀运算符)。此表示形式的优点是,您可以使用append/3谓词的单个事实定义在固定时间内将元素附加到列表中:

append(L1-T1, T1-T2, L1-T2).

一个用法示例:

?- append([1,2,3,4| T1]-T1, [5| T2]-T2, Result).
T1 = [5|T2],
Result = [1, 2, 3, 4, 5|T2]-T2.

如果有必要,在"正常"之间进行转换并不困难。列表和差异列表。我将此作为练习留给你。

答案 3 :(得分:2)

你担心问题的错误结束。结构共享只能通过将一个元素放到列表的开头来实现。该方法具有您想要的性能特征。由于定义了列表的方式,当您附加两个列表时,将复制整个第一个列表。在这种情况下,这将是整个列表。单项列表生成的垃圾显然要小得多。

如果你真的必须附加,请考虑向后构建列表,然后在结束时将其反转一次,这样便宜得多,或者使用差异列表,这样可以有效地追加到最后。

答案 4 :(得分:2)

您无法修改Prolog中的列表,但您可以创建一个未指定长度的列表:

main :-
    A = [1,2,3,4|_].

然后,您可以在SWI-Prolog中使用nth0/3插入元素:

:- initialization(main).

main :-
    A = [1,2,3,4|_],
    nth0(4,A,5),
    writeln(A).

插入此元素后,A = [1,2,3,4,5|_]

您还可以定义一个函数,将一个项目就地附加到列表的末尾,然后像这样使用它:

:- initialization(main).

append_to_list(List,Item) :-
    List = [Start|[To_add|Rest]],
    nonvar(Start),
    (var(To_add),To_add=Item;append_to_list([To_add|Rest],Item)).

main :-
    A = [1,2,3|_],
    append_to_list(A,4),
    append_to_list(A,4),
    writeln(A).

在此示例中,在附加这两个项目之后A = [1,2,3,4,4|_]

答案 5 :(得分:1)

由于Prolog的附加只接受列表,为什么我们不使用它来将我们的元素插入其中一个列表中。即。

% E = element, L = list, R = result
% e.g. add_elem_in_list ([1,2,3,4], 5, R).
add_elem_in_list(L, E, R) :- append(L, [E], R).