检查整个列表并检查Prolog中是否存在项
我的Prolog文件中的数据库如下->检查整个列表并检查Prolog中是否存在项,prolog,Prolog,我的Prolog文件中的数据库如下-> stage('crepe',2,'Stir the items into a consistent dough.',[],['pot','blender']). 我想使用以下查询并获得此结果-> ?- equipmentStage(‘crepe’, ‘blender’, Y). Y = [‘Stir the items into a consistent dough.’] . 我尝试使用以下代码,但当我尝试查询时,它返回一个空列表。所以Prolog得出
stage('crepe',2,'Stir the items into a consistent dough.',[],['pot','blender']).
我想使用以下查询并获得此结果->
?- equipmentStage(‘crepe’, ‘blender’, Y).
Y = [‘Stir the items into a consistent dough.’] .
我尝试使用以下代码,但当我尝试查询时,它返回一个空列表。所以Prolog得出的结论是不存在这样的东西。而当我尝试使用数据库中列表的第一个元素“pot”进行查询时,它会返回正确的输出。->
equipmentStage(Food,Equipment,StageTxt):-
findall(Txt, stage(Food, _, Txt, _, [Equipment]),StageTxt).
所以我的问题是,我怎样才能得到列表中第二项的正确结果?我是Prolog新手,非常感谢您的帮助 您的
findall
仅在有一台设备时匹配。您应该检查您的设备是否在配方的设备列表(Es
)中
equipmentStage(Food,Equipment,StageTxt):-
findall(Txt, (stage(Food, _, Txt, _, Es), member(Equipment, Es)),StageTxt).
如果您想要列出带有说明的设备:
equipment_desc(Food,[Equipment, StageTxt]):-
stage(Food, _, StageTxt, _, Es),
member(Equipment, Es).
如果您希望将它们作为列表而不是多个解决方案,则只需抓取所有设备并使用maplist
创建列表,如下所示:
pair_rev(H, T, [T, H]).
equipment_desc_list(Food, Ls):-
stage(Food, _, StageTxt, _, Es),
maplist(pair_rev(StageTxt), Es, Ls).
使用member,问题是findall检查并与它拥有的值进行比较。事实上,您有['pot','blender',如果您尝试只提供'blender',findall将拒绝它,您将返回一个空列表[]。所以,您可以使用member来比较您的“blender”,检查它是否存在于['pot'、'blender']中,然后它就可以很容易地执行了
stage('crepe',2,'Stir the items into a consistent dough.',[],['pot','blender']).
t(A,B,S):-
stage(_,_,_,_,W),
member(B,W),
findall(C,stage(A,_,C,_,W),S).
?-t('crepe','blender',S).
S = ['Stir the items into a consistent dough.']
下面是我使用findall
(以及类似的谓词,如setof
或bagof
)的两条主要规则:
不要使用findall
。您可能不需要结果列表。回溯结果通常是你想要的。定义通过回溯枚举解决方案的谓词
如果您真的想要一个列表(您可能不想要),请按照以下步骤进行:从步骤1获取谓词定义。对其应用findall
;切勿将复杂查询放入findall
因此,针对您的问题,第1步:
food_equipment_stage(Food, Equipment, Stage) :-
stage(Food, _, Stage, _, Equipments),
member(Equipment, Equipments).
这给出了一个单一的答案:
?- food_equipment_stage(crepe, blender, Stage).
Stage = 'Stir the items into a consistent dough.'.
有了更大的知识库,这将一一列举答案
你是否绝对确定你需要一份清单,而你很可能不需要?如果是(但可能不是),在步骤2中,可以很容易地将findall
应用于步骤1中的定义(但您可能不想):
这将为您提供一个列表:
?- food_equipment_stages(crepe, blender, Stages).
Stages = ['Stir the items into a consistent dough.'].
谢谢你,这很有效!我还有一个问题,比如说我想把这两台设备都退回,就像这样->[[pot'搅拌成一致的面团]],[blender'搅拌成一致的面团]]。这是怎么做到的?谢谢你详尽的回答!不幸的是,它必须在一个列表中。但我真的很想知道你怎么能让输出看起来像这样->[[pot'搅拌成一致的面团]],[blender'搅拌成一致的面团]]。你也能帮我一下吗?findall([设备,舞台]、food\u设备\u舞台(食品,设备,舞台)、设备和舞台)
那setof/3
呢?
food_equipment_stages(Food, Equipment, Stages) :-
findall(Stage, food_equipment_stage(Food, Equipment, Stage), Stages).
?- food_equipment_stages(crepe, blender, Stages).
Stages = ['Stir the items into a consistent dough.'].