Prolog实现从自定义电影数据库按角色查询对应电影
Prolog按角色名查询对应电影的实现方案
现有结构的问题
你当前的数据库设计存在3个影响实现的问题:
- 谓词命名语法错误:
data base中间带空格,不符合Prolog谓词无空格的命名规则,会直接触发语法报错 - 人名存储逻辑冗余:角色、导演的姓名被拆分成了字词列表,查询时需要额外做拼接匹配,增加不必要的逻辑复杂度
- 存储结构不符合Prolog设计习惯:所有电影被包裹在一个列表中作为单个事实存储,查询时需要手动递归遍历整个列表,无法利用Prolog本身的事实索引优化,后续增删数据也很麻烦
推荐优化方案
优先调整数据库结构,把单部电影作为独立的事实存储,人名直接保存为完整姓名字符串,不需要拆分成子列表:
% 电影事实结构:movie(电影名称, 主要角色全名列表, 导演全名列表) movie("Titanic", ["Jack Dawson", "Rose DeWitt Bukater"], ["James Cameron"]). movie("Hulk", ["Bruce Banner", "Betty Ross"], ["Ang Lee"]).
基于这个结构,查询谓词的实现非常简洁,只需要判断输入的角色名存在于对应电影的角色列表中即可:
% 调用示例:find_movies_by_character("Bruce Banner", Movie). 会返回 Movie = "Hulk" find_movies_by_character(TargetCharacter, TargetMovie) :- movie(TargetMovie, CharacterList, _), member(TargetCharacter, CharacterList).
如果需要查询所有匹配的电影,直接在Prolog交互端输入查询语句后,输入分号即可遍历全部结果。
注意:不同Prolog方言对字符串的支持存在差异,如果运行时出现类型不匹配的问题,可以把双引号包裹的字符串替换为单引号包裹的原子,查询逻辑不需要修改。
兼容原有结构的实现方案
如果你不想调整已有的嵌套列表存储结构,可以先修正语法错误,再通过辅助谓词实现姓名拼接匹配:
% 修正语法错误后的原始数据库 database([ movie(["Titanic"], [["Jack", "Dawson"] ,["Rose", "DeWitt", "Bukater"]], ["James","Cameron"] ), movie(["Hulk"], [["Bruce", "Banner"] ,["Betty", "Ross"]], ["Ang","Lee"] ) ]). % 辅助谓词:将拆分存储的姓名字词拼接为带空格的完整姓名 join_name([SinglePart], SinglePart). join_name([FirstPart|RestParts], FullName) :- join_name(RestParts, RestFullName), atom_concat(FirstPart, ' ', FirstWithSpace), atom_concat(FirstWithSpace, RestFullName, FullName). % 适配原有结构的查询谓词 find_movies_by_character(TargetCharacter, TargetMovie) :- database(AllMovies), member(movie([TargetMovie], AllCharParts, _), AllMovies), member(SingleCharParts, AllCharParts), join_name(SingleCharParts, TargetCharacter).
内容的提问来源于stack exchange,提问作者Peter Pereira
相关产品推荐
相关产品推荐

