我有一个SWI-Prolog代码:
class(c1, 'Vehicle').
class(c2, 'Car').
class(c3, 'Motorcycle').
class(c4, 'Company').
class(c5, 'RentalStation').
class(c6, 'Person').
我想写一条规则来检查类的所有谓词是否都有不同的名称(第二个参数)。我应该怎么写这条规则?
答案 0 :(得分:2)
另一种可能性是使用bagof / 3和maplist / 2。要获得所有名称,您可以像这样使用bagof / 3:
?- bagof(Y,X^class(X,Y),List).
List = ['Vehicle', 'Car', 'Motorcycle', 'Company', 'RentalStation', 'Person'].
要获得所有ID,您可以像这样使用bagof / 3:
?- bagof(X,Y^class(X,Y),List).
List = [c1, c2, c3, c4, c5, c6].
您可以使用maplist / 2来定义描述具有唯一元素的列表的谓词,让我们将其称为uniques / 1,如下所示:
:- use_module(library(apply)). % for maplist/2
uniques([]).
uniques([X|Xs]) :-
maplist(dif(X),Xs),
uniques(Xs).
您可以查询此谓词,以确定它确实描述了您想要的内容:
?- uniques([]).
true.
?- uniques([a,b,c]).
true.
?- uniques([a,b,c,a]).
false.
在此基础上,您可以检查名称或ID是否如此唯一:
?- bagof(Y,X^class(X,Y),List), uniques(List).
List = ['Vehicle', 'Car', 'Motorcycle', 'Company', 'RentalStation', 'Person'].
?- bagof(X,Y^class(X,Y),List), uniques(List).
List = [c1, c2, c3, c4, c5, c6].
如果你想得到一个答案,显示列表中的重复,你可以像这样定义一个谓词list_reps / 2:
:- use_module(library(lists)). % for append/3
list_reps([],[]).
list_reps([X|Xs],Ds1) :-
x_reps_others_fromlist(X,Ds,Os,Xs),
list_reps(Os,Ds0),
append(Ds,Ds0,Ds1).
x_reps_others_fromlist(_X,[],[],[]).
x_reps_others_fromlist(X,[X|Ds],Os,[X|Ys]) :-
x_reps_others_fromlist(X,Ds,Os,Ys).
x_reps_others_fromlist(X,Ds,[Y|Os],[Y|Ys]) :-
dif(Y,X),
x_reps_others_fromlist(X,Ds,Os,Ys).
现在让我们看看这个谓词在起作用:
?- list_reps([],R).
R = [].
?- list_reps([a,b,c],R).
R = [] ;
false.
?- list_reps([a,b,c,a],R).
R = [a] ;
false.
?- list_reps([a,b,c,a,b],R).
R = [a, b] ;
false.
?- list_reps([a,b,c,a,b,a],R).
R = [a, a, b] ;
false.
如您所见,元素在重复显示时会在第二个列表中显示。使用您提供的事实类/ 2,既没有重复的名称也没有重复的ID:
?- bagof(Y,X^class(X,Y),List), list_reps(List,R).
List = ['Vehicle', 'Car', 'Motorcycle', 'Company', 'RentalStation', 'Person'],
R = [] ;
false.
?- bagof(X,Y^class(X,Y),List), list_reps(List,R).
List = [c1, c2, c3, c4, c5, c6],
R = [] ;
false.
要看到两个反例,我们再添加两个事实:
class(c1, 'Vehicle').
class(c2, 'Car').
class(c3, 'Motorcycle').
class(c4, 'Company').
class(c5, 'RentalStation').
class(c6, 'Person').
class(c6, 'Person'). % <- new
class(c7, 'Person'). % <- new
现在上述查询告诉您名称'Person'
重复两次,ID c6
重复一次:
?- bagof(Y,X^class(X,Y),List), list_reps(List,R).
List = ['Vehicle', 'Car', 'Motorcycle', 'Company', 'RentalStation', 'Person', 'Person', 'Person'],
R = ['Person', 'Person'] ;
false.
?- bagof(X,Y^class(X,Y),List), list_reps(List,R).
List = [c1, c2, c3, c4, c5, c6, c6, c7],
R = [c6] ;
false.
出于比较原因:上面进一步检查名称或ID是否唯一的两个查询都失败并附加了其他事实:
?- bagof(Y,X^class(X,Y),List), uniques(List).
false.
?- bagof(X,Y^class(X,Y),List), uniques(List).
false.
答案 1 :(得分:0)
您可以先使用findall / 3谓词来获取所有类名的列表,然后只需检查该列表是否没有重复元素,例如:
if(v<10)
{
if(v>20)
System.out.println("20 IF");
}
// now the following else statement will be of ""if(v<10)"" and not
// ""if(v>20)""
else
{
System.out.println("20 ELSE"); // its not of (20 ELSE)
}
这里我们首先将所有名称都放入Names变量中,然后使用一些&#34;技巧&#34;检查所有元素是否唯一,即我们使用sort / 2谓词,它不仅排序,而且删除重复(与msort / 2不同)。之后,我们只是比较原始列表和重复数据删除列表的长度。
更新:如果您需要检查每个特定ID的唯一性,您可以使用另一个findall / 3调用来获取所有ID的列表,然后将maplist / 2和上面的解决方案结合起来检查每个id的唯一性。将所有内容组合在一起,我们得到:
findall(Name, class(_, Name), Names),
sort(Names, Unique),
length(Names, X),
length(Unique, X).