You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Prolog中实现检索指定食谱全步骤食材的谓词

实现Prolog的retrieveIngredients谓词

嘿,我来帮你搞定这个Prolog谓词的实现!首先先把你现有的知识库贴出来,方便对照:

step('pancakes', 1, 'mix butter and sugar in a bowl', [butter, sugar], [bowl]).
step('pancakes', 2, 'add eggs', [eggs], []).
step('pancakes', 3, 'mix flour and baking powder', [flour, baking powder], []).

你需要实现的retrieveIngredients(X,Y),要能在查询retrieveIngredients('pancakes',Y)时返回所有用到的食材。这里有两种实用的实现方式:

方式一:用findall + flatten(简洁高效)

这种方式直接用Prolog内置的谓词来完成收集和整理,代码非常直观:

retrieveIngredients(Dish, Ingredients) :-
    % 收集所有对应菜品步骤里的食材列表
    findall(StepIngredients, step(Dish, _, _, StepIngredients, _), AllIngredientsLists),
    % 把嵌套的列表展开成一维的食材列表
    flatten(AllIngredientsLists, Ingredients).

逻辑拆解:

  1. findall/3会遍历所有和目标菜品Dish相关的step事实,把每个步骤的食材列表(也就是每个step的第四个参数)收集起来,得到一个嵌套列表:[[butter,sugar], [eggs], [flour,baking powder]]。
  2. flatten/2把这个嵌套列表“压平”成一维列表,最终得到所有食材的集合:[butter, sugar, eggs, flour, baking powder]。

注:你给出的预期结果里没有sugar,应该是笔误哦,毕竟原知识库的第一步明确用到了sugar。如果确实需要过滤掉某些食材,可以在最后加额外的筛选逻辑~

方式二:递归遍历步骤(手动实现,更灵活)

如果你想手动控制遍历过程,不用内置的findall,可以用递归的方式逐个步骤收集食材:

% 对外暴露的主谓词
retrieveIngredients(Dish, Ingredients) :-
    retrieveIngredients(Dish, 1, [], Ingredients).

% 递归子谓词:收集当前步骤的食材,继续下一个步骤
retrieveIngredients(Dish, StepNum, Accumulator, FinalIngredients) :-
    step(Dish, StepNum, _, StepIngredients, _),
    % 把当前步骤的食材加到累加器里
    append(Accumulator, StepIngredients, NewAccumulator),
    % 计算下一个步骤号
    NextStep is StepNum + 1,
    % 递归处理下一个步骤
    retrieveIngredients(Dish, NextStep, NewAccumulator, FinalIngredients).

% 基础情况:当前步骤号没有对应的步骤时,返回累加的食材
retrieveIngredients(_, StepNum, Accumulator, Accumulator) :-
    \+ step(_, StepNum, _, _, _).

这种方式从步骤1开始,一步步把每个步骤的食材加到累加器中,直到没有更多步骤为止,最终返回所有收集到的食材。

额外优化:去重与排序

如果你的菜谱里有重复使用的食材,想要去重的话,可以在第一种方式的最后加上sort/2(排序的同时自动去重):

retrieveIngredients(Dish, Ingredients) :-
    findall(StepIngredients, step(Dish, _, _, StepIngredients, _), AllIngredientsLists),
    flatten(AllIngredientsLists, Unfiltered),
    sort(Unfiltered, Ingredients).

不过sort会改变食材的顺序,如果想要保持步骤中的出现顺序且去重,就需要自定义一个去重谓词啦。

内容的提问来源于stack exchange,提问作者Coderman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 21:37:36