检查整个列表并检查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得出

我的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.'].