List 检查两个列表是否有公共元素
基本上,我有一个称为common_elements(List1,List2)的谓词,这个谓词的目的是检查List1是否至少有一个属于List2的元素 例如:List 检查两个列表是否有公共元素,list,prolog,List,Prolog,基本上,我有一个称为common_elements(List1,List2)的谓词,这个谓词的目的是检查List1是否至少有一个属于List2的元素 例如: ?- common_elements([1,2,3,4,5,6],[6]). true. ?- common_elements([1,2,3],[2]). true. ?- common_elements([1,2,3],[6]). false. ?- common_elements([P1,P2,P3,P4,P5,P6],[P7,P
?- common_elements([1,2,3,4,5,6],[6]).
true.
?- common_elements([1,2,3],[2]).
true.
?- common_elements([1,2,3],[6]).
false.
?- common_elements([P1,P2,P3,P4,P5,P6],[P7,P8,P6]).
true.
?- common_elements([1,2,3],[2]).
true.
?- common_elements([1,2,3],[6]).
false.
?- common_elements([P1,P2,P3,P4,P5,P6],[P7,P8,P6]).
P1 = P7.
所以对于数字,这很有效,但是如果我输入变量,它会统一变量,而不是检查它们是否在第二个列表中
例如:
?- common_elements([1,2,3,4,5,6],[6]).
true.
?- common_elements([1,2,3],[2]).
true.
?- common_elements([1,2,3],[6]).
false.
?- common_elements([P1,P2,P3,P4,P5,P6],[P7,P8,P6]).
true.
?- common_elements([1,2,3],[2]).
true.
?- common_elements([1,2,3],[6]).
false.
?- common_elements([P1,P2,P3,P4,P5,P6],[P7,P8,P6]).
P1 = P7.
所以,正如你所看到的,对于数字,它工作得很好,但由于某种原因,如果类型变量,它将它们统一起来,而不是仅仅比较它们,而且似乎你不明白为什么
节目:
common_elements(L1,L2) :- common_elements(L1,L2,[]).
common_elements([],_,AC) :- length(AC,C),
C >= 1.
common_elements([P|_],L2,AC) :- member(P,L2),!,
append(AC,[P],NAC),
common_elements([],L2,NAC).
common_elements([P|R],L2,AC) :- \+ member(P,L2),!,
common_elements(R,L2,AC).
成员/2
谓词将执行统一。事实上,例如:
?- member(P1, [P2]).
P1 = P2.
您可以利用来避免统一,因此:
如果Term1
等同于Term2
,则为True。变量仅与共享变量相同
所以我们在这里可以做的是检查一个变量是否与另一个变量等价:
membereq(X, [H|_]) :-
X == H.
membereq(X, [_|T]) :-
membereq(X, T).
因此,我们可以检查:
common_elements([H|_], L2) :-
membereq(H, L2).
common_elements([_|T], L2) :-
common_elements(T, L2).
然后,这将回答以下问题:
?- common_elements([1,2,3,4,5,6],[6]).
true ;
false.
?- common_elements([1,2,3,4,5,6],[6]).
true ;
false.
?- common_elements([1,2,3],[2]).
true ;
false.
?- common_elements([1,2,3],[6]).
false.
?- common_elements([P1,P2,P3,P4,P5,P6],[P7,P8,P6]).
true ;
false.
成员/2
谓词将执行统一。事实上,例如:
?- member(P1, [P2]).
P1 = P2.
您可以利用来避免统一,因此:
如果Term1
等同于Term2
,则为True。变量仅与共享变量相同
所以我们在这里可以做的是检查一个变量是否与另一个变量等价:
membereq(X, [H|_]) :-
X == H.
membereq(X, [_|T]) :-
membereq(X, T).
因此,我们可以检查:
common_elements([H|_], L2) :-
membereq(H, L2).
common_elements([_|T], L2) :-
common_elements(T, L2).
然后,这将回答以下问题:
?- common_elements([1,2,3,4,5,6],[6]).
true ;
false.
?- common_elements([1,2,3,4,5,6],[6]).
true ;
false.
?- common_elements([1,2,3],[2]).
true ;
false.
?- common_elements([1,2,3],[6]).
false.
?- common_elements([P1,P2,P3,P4,P5,P6],[P7,P8,P6]).
true ;
false.
使用内置,如您标记的SWI和
ordset
是不受欢迎的
:- use_module(library(ordsets)).
common_elements(A, B) :-
sort(A, AS), % can omit if using sorted A list
sort(B, BS), % can omit if using sorted B list
ord_intersect(As, Bs).
一些例子:
t1 :-
common_elements([a, b, c], [d, e, f]).
t2 :-
common_elements([a, b, c], [c, d, e]).
t3 :-
common_elements([a, b, c], [_A, _B, _C]).
t4 :-
common_elements([a, b, C], [d, e, C]).
t5 :-
common_elements([a, b, _C], [d, e, _F]).
tests :-
\+ t1,
t2,
\+ t3,
t4,
\+ t5.
注意:使用
sort/2
而不是list\u to\u set/2
,因为后者保留了变量。此外,使用ord_intersect/2
overintersection/3
,因为后者可能会产生意外的结果。如果您使用许多集合操作,您可能会发现在整个过程中使用有序列表(ordset
)是值得的。使用内置的,因为您标记了SWI和ordset
:- use_module(library(ordsets)).
common_elements(A, B) :-
sort(A, AS), % can omit if using sorted A list
sort(B, BS), % can omit if using sorted B list
ord_intersect(As, Bs).
一些例子:
t1 :-
common_elements([a, b, c], [d, e, f]).
t2 :-
common_elements([a, b, c], [c, d, e]).
t3 :-
common_elements([a, b, c], [_A, _B, _C]).
t4 :-
common_elements([a, b, C], [d, e, C]).
t5 :-
common_elements([a, b, _C], [d, e, _F]).
tests :-
\+ t1,
t2,
\+ t3,
t4,
\+ t5.
注意:使用
sort/2
而不是list\u to\u set/2
,因为后者保留了变量。此外,使用ord_intersect/2
overintersection/3
,因为后者可能会产生意外的结果。如果您使用许多集合操作,您可能会发现在整个过程中使用有序列表(ordset
)是值得的。因为member/2
将统一元素。因为member/2
将统一元素。