Prolog合并两个列表

时间:2015-10-14 07:15:41

标签: list recursion merge prolog

我需要在Prolog中合并两个列表。输入应该是谓词$insert = "INSERT INTO `info` (`id`,`user`,`roll`,`mob`,`pic`) VALUES (NULL,'$user','$roll','$mob','$pic')";

Visual Hint

应该像这样工作:

merge/3

我尝试过:

?- merge([6,4,b,8], [5,b,s,6], X).
X = [6, 4, b, 8, 5, s].

我得到了什么:

%rules
merge(A, B, X):- 
    merge(A, B, B, X).

merge([], X, _, X).
merge([Head|L1], [Head|L2], Tmp, [Head|X]) :-
    merge(L1, L2, Tmp, X),
    !.
merge(L1, [_|L2], Tmp, X) :-
    merge(L1, L2, Tmp, X),
    !.
merge([A|L1], [], Tmp, [A|X]) :-
    merge(L1, Tmp, Tmp, X),
    !.

我的期望:

?- merge([1,2,a,3], [5,d,a,1], X).
X = [1, 2, a, 3, 5, d, a, 1].

2 个答案:

答案 0 :(得分:2)

如果元素的顺序不是以某种方式取决于两个输入列表的顺序,那么这是一个惯用的Prolog解决方案:

?- append([6,4,b,8], [5,b,s,6], A), sort(A, B).
A = [6, 4, b, 8, 5, b, s, 6],
B = [4, 5, 6, 8, b, s].

如果订单很重要,您需要详细解释。

对您展示的代码提出一些意见。您为谓词选择的名称:"加入"和"合并"与你似乎想要实现的目标有着明显的意义不同("加入"如在关系数据库中,"合并"如在"合并两个有序列表")。你正在做的是"union"(顺便说一下,点击这个链接阅读代码!)。

此外,将一个切割作为子句体的最后一个子目标几乎总是错误(不是错误,而是错误)。对谓词有多个明显相互排斥的子句(作为merge/4的4个子句中的最后3个)通常是设计缺陷(不是错误)。

答案 1 :(得分:1)

这可以通过重写内置谓词来完成!例如:

my_append([], R, R) .
my_append([H|T], R1, [H|R2]) :-
    my_append(T, R1, R2).


my_member(H, [H|_]).
my_member(H, [_|T]) :-
    my_member(H, T).

所以,我可以说将L与空列表合并给出了这个列表L

merge(L, [], L).

现在,要合并两个列表,我会查看第二个列表的第一个元素。

如果它在第一个列表中,我将其忽略,并将第一个列表与第二个列表的其余部分合并。

如果没有,我在第一个列表的末尾添加第一个元素,并将新的第一个列表与第二个列表的其余部分合并。

我必须说这不是很有效!!

merge(L, [H| T], R) :-
    (   my_member(H, L)
    ->  merge(L, T, R)
    ;   my_append(L, [H], L1),
        merge(L1, T, R)).