由于我的Prolog数据结构受到了批评,我在这里向专家们咨询替代方案。
例如,我有一个XML格式的食谱描述数据集。
<recipeml fileversion="13.8.2014">
<recipe>
<head>
<title>Green Soup</title>
</head>
<ing-div type="titled">
<title>soup</title>
<ingredients>
<ing>
<amt><qty>500</qty><unit>gramm</unit></amt>
<item>pea</item>
</ing>
<ing>
<amt><qty>200</qty><unit>ml</unit></amt>
<item>cream</item>
</ing>
...
</ingredients>
</ing-div>
<directions>
<step>Do something, cooking ....</step>
<step>Next do again something...</step>
...
</directions>
</recipe>
<recipe>
...
</recipe>
...
</recipeml>
我选择使用列表将其以迭代的元素树形式存储在Prolog中:
database([element('recipeml',[version=0.5],
[element('recipe',[],
[element('head',[],
[element('title',[],['Green Soup']
)]
),
element('ing-div',[type=titled],
[element('title',[],['soup']),
element('ingredients',[],
[element(ing,[],
[ element(amt,[],
[ element(qty,[],['500']), element(unit,[],[gramm]),]),
element(item,[],['pea'])
]),
element(ing,[],
[ element(amt,[],
[ element(qty,[],['200']), element(unit,[],[ml]),]),
element(item,[],['pea'])
])
]
)]
)]
),
element('recipe',[],...
)]
)]).
我想要做的是根据用户输入轻松查找食谱。用户可能会输入一种食材或者菜谱名称的部分。
实际上,我已经通过了元素的遍历
ask_element(Name, Child, Parent) :-
(
member( element(Name,_,Child),Parent)
;
member( element(_,_,NewParent),Parent),
[_|_] = NewParent,
ask_element(Name, Child, NewParent)
).
我使用特殊成分得到了所有的配方。
findall(RTitle,
(
ask_element('recipe',RKnot,Knot),
ask_element('item',TmpIng,RKnot),
contains(TmpIng,Ingredient),
[Ing|_] = TmpIng, % avoid brackets [Egg]
define_xml_knot(['head','title'],_,RKnot,TmpRTitle),
[RTitle|_] = TmpRTitle % avoid brackets [Soup]
,Bag),
我的结果是食谱标题的列表。如果输入了一份配料清单,我需要进行第二个分析步骤,以获取与大多数匹配配料的食谱。也许这不是真正的Prolog风格?
一个想法是,根据Paulo Moura(感谢)的评论,将数据排列为
recipe(IDnumber,'Green Soup',ingredients(item(500,gramm,'pea'),item(200,ml,'cream')),steps('Do something','Next step do again something')).
我不确定这是否真的有用。如果我要寻找某个特定成分的食谱,我必须逐步查看每个食谱中的每个项目,以确定我正在寻找的成分(或部分单词)是否包含在其中。如果我想添加一个新的描述符,例如 "
level(easy)
",我必须更改所有数据调用,因为recipe()
中元素的数量发生了变化。使用element(element...)
结构,我不必更改调用。但是,通过仅返回ID号码作为响应,然后我可以在一个“调用”(recipe(123,X,Y,Z)
)中获取整个食谱以进行进一步处理。实际上,我将“字符串文本列表”作为响应返回,就像您在上面的“Bag”中看到的那样...这是我的Prolog首个应用程序,因此我对适当的数据存储不太熟悉。我会感激每一个提示。
recipe(IDnumber,'Green Soup',ingredients([item(500,gramm,'pea'),item(200,ml,'cream')]),steps(['Do something','Next step do again something'])).
。将成分和步骤作为具有与食谱相关的元数的复合术语只会使处理变得更加复杂,没有任何好处。这也更接近您呈现的XML结构(假设这是您的意图)。 - Paulo Moura