List SICStus Prolog列表
理解Prolog如何工作有困难。我正在尝试编写一个规则,将三个整数列表作为输入(表示集合),并将属于第一个和第二个列表的整数放入第三个列表 例如:List SICStus Prolog列表,list,prolog,prolog-lists,List,Prolog,Prolog Lists,理解Prolog如何工作有困难。我正在尝试编写一个规则,将三个整数列表作为输入(表示集合),并将属于第一个和第二个列表的整数放入第三个列表 例如: ?-inter([10,20,30,40],[10,50,40,60], List3 ) List3 = [10, 40] 到目前为止,我有一个,可以识别列表是否包含某个字母: mymember(X,[X|T]). mymember(X,[H|T]) :- mymember(X,T). 实际上,有一个内置的库可以为您整理这些内容,称为ordset
?-inter([10,20,30,40],[10,50,40,60], List3 )
List3 = [10, 40]
到目前为止,我有一个,可以识别列表是否包含某个字母:
mymember(X,[X|T]).
mymember(X,[H|T]) :- mymember(X,T).
实际上,有一个内置的库可以为您整理这些内容,称为ordsets
inter(X, Y, Z) :-
list_to_ord_set(X, L1),
list_to_ord_set(Y, L2),
ord_intersection(L1, L2, Z).
使用示例输入,您可以得到以下结果
| ?- inter([10,20,30,40],[10,50,40,60],X).
X = [10,40] ? ;
no
inter(Xs,Ys,Zs)
将在Zs中的每个元素也在Xs和Ys中时为真
但Z是未知的,因此需要更具建设性的方法。
这里是:在Xs上迭代,并将Ys中的每个元素存储在Zs中
迭代的一个例子是mymember/2,您可以看到它需要一个递归谓词。
上面语句的另一个惯用部分是存储在Zs
,Prolog有一种特殊的方法来做这些事情,使用模式匹配
inter([X|Xs], Ys, [X|Zs]) :-
mymember(X, Ys), inter(Xs, Ys, Zs).
您将需要使用其他2个子句来完成inter/3:基本递归,即当所有Xs元素都已被处理时,以及当X不是Ys的成员时。使用内置的
member/2
和setof\3
尝试类似的操作:
set_intersection( As , Bs , Xs ) :-
set_of( X , ( member(X,As) , member(X,Bs) ) , Xs )
.
需要注意的是,如果列表As
和Bs
没有共同元素,则此操作将失败。另一种选择是使用findall/3
而不是set\u/3
findall/3
如果目标未实现,将返回并清空列表,而不是失败:
set_intersection( As , Bs , Xs ) :-
findall( X , ( member(X,As) , member(X,Bs) ) , Xs )
.
但是findall/3
返回一个包(允许重复)而不是一个集合(不允许重复),因此如果您的两个源列表不是集合,您将无法获得集合
member/2
是一个内置谓词,它将其第一个参数与列表中的一个元素(相当于
member(X,[X|_).
member(X,[_|Xs) :- member(X,Xs) .
最后,@chac在他的回答中指出,您可以递归遍历列表
set_intersection( [] , _ , [] ) . % the intersection of the empty set with anything is the empty set.
set_intersection( [A|As] , Bs , [A|Xs] ) :- % if the list is non-empty,
member(A,Bs) , % - and A is a member of the 2nd set
! , % - we cut off alternatives at this point (deterministic)
set_intersection( As , Bs , Xs ) % - and recurse down on the tail of the list.
.
set_intersection( [_|As] , Bs , Xs ) :- % if the list is non-empty, and A is NOT a embmer of the 2nd set
set_intersection( As , Bs , Xs ) % we just recurse down on the tail of the list.
.
@chac的技术在运行时构建结果列表,类似于:
[a|X]
[a,b|X]
[a,b,c|X]
最终的统一,即空列表的特例,将列表的未绑定尾部统一为使列表完整的[]
,因此最终的[a,b,c | X]
[a,b,c]
一点开场白的魔力。另一种可能更容易理解的方法是将辅助谓词与累加器一起使用:
%
% set_intersection/3: the public interface predicate
%
set_intersection( As , Bs , Xs ) :-
set_intersection( As , Bc , [] , T ) % we seed our accumulator with the empty list here
.
%
% set_intersection/4: the private worker bee predicate
%
set_intersection( [] , _ , T , Xs ) :- % since our accumulator is essentially a stack
reverse(T,Xs) % we need to reverse the accumulator to
. % put things in the expected sequence
set_intersection( [A|As] , Bs , T , Xs ) :-
member( A, Bs ) ,
! ,
T1 = [A|T] ,
set_intersection( As , Bs , T1 , Xs )
.
set_intersection( [_|As] , Bs , T , Xs ) :-
set_intersection( As , Bs , T , Xs )
.
你载入图书馆了吗?使用_模块(库(ordset))加载它