【问题标题】:prolog two lists are exactly the sameprolog 两个列表完全一样
【发布时间】:2014-04-28 01:13:30
【问题描述】:

如果两个列表完全相同(元素的顺序很重要),我想编写一个返回 true 的函数。

我是这样尝试的:

same([ ], [ ]).   
same([H1|R1], [H2|R2]):-
    H1 == H2,
    same(R1, R2).

当两个列表相同时它返回 true,我也希望如果我有

?- same(X, [1, 2, 3]).

我希望它返回

X = [1, 2, 3].

但是如果输入是这样的话就不行了。以下是我得到的一些示例输出:

?- same([1, 2], [1, 2]).

true.

?- same([2, 1], [1, 2]).

false.

?- same(X, [1, 2, 3]).

false.

?- same([1, 2, 3], [1, 2, X]).

false.

如何解决?

【问题讨论】:

    标签: list prolog


    【解决方案1】:

    问题在于您使用的是==/2(检查两个项目是否实例化相同)而不是=/2(检查两个项目是否统一或统一)。改成统一就好了:

    same([], []).
    
    same([H1|R1], [H2|R2]):-
        H1 = H2,
        same(R1, R2).
    

    那么这将具有您正在寻找的行为:

    | ?- same(X, [1, 2, 3]).
    
    X = [1,2,3] ? a
    
    no
    | ?- same([1, 2], [1, 2]).
    
    (1 ms) yes
    | ?- same([2, 1], [1, 2]).
    
    no
    | ?- same([1, 2, 3], [1, 2, X]).
    
    X = 3
    
    (1 ms) yes
    | ?- same([A,B,C], L).
    
    L = [A,B,C]
    
    yes
    % In this last example, A, B, and C are variables. So it says L is [A,B,C],
    % whatever A, B, and C are.
    

    如果在Prolog中查询X == 3,而X没有绑定值3,或者只是未绑定,就会失败。如果X是未绑定的,你查询X = 3,那么Prolog会将X(绑定它)和3统一起来,就会成功。

    有关=/2==/2之间区别的更多信息,请参阅What is the difference between == and = in Prolog?

    您还可以使用maplist 获得一个不错的紧凑解决方案。 maplist 对于遍历列表非常方便:

    same(L1, L2) :- maplist(=, L1, L2).
    

    这里仍然使用统一(=/2),原因与上述完全相同。


    最后,正如@Boris 指出的那样,在 Prolog 中,统一谓词将适用于整个列表。在这种情况下,这就足够了:
    same(L1, L2) :- L1 = L2.
    

    或等效:

    same(L, L).  % Would unify L1 and L2 queried as same(L1, L2)
    

    如果列表相同,这将成功,或者将尝试通过依次统一每个元素来统一它们。

    | ?- same([1,2,X], [1,2,3]).    % Or just [1,2,X] = [1,2,3]
    
    X = 3
    
    yes
    | ?- same([1,2,X], [1,2,3,4]).  % Or just [1,2,X] = [1,2,3,4]
    
    no
    

    为了说明,之前更复杂的方法被认为是列表处理中的练习。但是比较和/或统一列表的最简单和最正确的方法是L1 = L2

    【讨论】:

    • 这个答案很奇怪(就像原来的问题一样)。为什么不直接统一这两个列表呢?
    • @Boris 如果您认为这是一个列表处理练习,这个问题并不奇怪。但你的答案是对的。当我在说明列表处理之后提供了一个答案时,我忽略了最简单的方法。感谢您指出。
    • 实际上,相同(X,X)。已经足够了,但这实际上是 =(X, X)。
    • 如果你不关心订单,你会怎么做?
    • @hiswendy 最简单的做法是使用msort 将它们整理好,而不是删除重复项,然后尝试统一它们。所以,same(L1, L2) :- msort(L1, S1), msort(L2, S2), S1 = S2. 一个更长但不太必要的方法是逐个元素地使用select/3
    猜你喜欢
    • 1970-01-01
    • 2021-08-03
    • 2016-01-12
    • 2013-02-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多