查找所有的重复项。

3

我输入了我的信息:

likesdrinking(tom).
likesdrinking(sally).
likesdrinking(holly).

likespainting(tom).
likespainting(sally).
likespainting(chad).
likespainting(margo).

likesskating(tom).
likesskating(holly).
likesskating(margo).
likesskating(matt).
likesskating(cass).

如果我想找到喜欢喝酒、画画或滑冰的人,我会使用 findall 方法,它的用法如下:

findall(X,(likesdrinking(X),likesskating(X),likespainting(X)),X). 

它将为那些喜欢多次的人给出结果。 X = tom,sally,holly,tom,sally,chad ......等等

但我该如何使其仅返回一个答案而不是重复的内容呢? 所以它应该是

X = tom, sally, holly, chad, margo, matt , cass 

1
实际上,根据您的指示,您会得到那些喜欢喝酒、滑冰和绘画的人。如果要获取符合一个或多个条件的匹配项,请使用OR分隔符“;”而不是AND分隔符“,”。 - David Tonhofer
1个回答

1
你想要标准的 setof/3 谓词:
?- setof(X, (likesdrinking(X),likesskating(X),likespainting(X)), L).
L = [tom].

?- setof(X, (likesdrinking(X),likesskating(X)), L).
L = [holly, tom].

?- setof(X, (likesdrinking(X),likespainting(X)), L).
L = [sally, tom].

正如David在他的评论中所指出的,如果你想构建一个至少包含其中一项活动喜欢的人的列表(不重复):

?- setof(X, (likesdrinking(X); likesskating(X); likespainting(X)), L).
L = [cass, chad, holly, margo, matt, sally, tom].

对于像“谁喜欢滑冰但不喝酒”这样的问题,你必须小心目标的顺序。以下查询是错误的:

?- setof(X, (\+ likesdrinking(X), likesskating(X)), L).
false.

为什么?当你调用 \+ likesdrinking(X) 时,变量 X 尚未绑定,会失败,因为有多个人喜欢饮酒。你需要改为以下代码:
?- setof(X, (likesskating(X), \+ likesdrinking(X)), L).
L = [cass, margo, matt].

likesskating(X) 的目标是限制 X,然后 \+ likesdrinking(X) 将检查该特定人是否不喜欢饮酒。一般来说,在使用否定 (\+/1) 与非基础目标时要小心。


1
请注意,如果setof/3找不到任何内容,则会失败(这在逻辑上是正确的),而findall/3则将其第三个参数与空列表(口语上称为空列表)统一,如果它找不到任何东西,这会破坏Prolog的“失败然后重做”策略,并且更适用于那些非逻辑工作的代码段。 - David Tonhofer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接