我有一个包含标题和分数的列表列表,如:[ [ 'title1',100 ],[ 'title2',200 ],...]
。如果我有一定的分数,我必须制作一个返回标题的谓词。 find_title(Score,List,ListOfTitles)
。另外一些分数可能与我试图将其存储在List中的原因相同。如果有多个分数具有相同的分数。
我试过了:
return_title(Score,List,[H|T]):-
return_title(Score,List,T),
member([X,Score],List),
H=X.
但它没有工作......关于另一个实现的任何想法?
答案 0 :(得分:7)
以声明的方式思考:只考虑谓词应该描述的内容。它是得分,标题和得分列表之间的关系,以及与第一个参数中的得分匹配的标题列表。我发现找到谓词的描述性名称很有帮助,人们可以立刻看到哪个参数是什么。那么为什么不选择score_list_titles / 3之类的东西。然后我想一下我的描述中有哪些案例要涵盖。对于这种关系,我看到三种情况:
score_list_titles(_S,[],[]). % 1: if list is empty titles is empty
score_list_titles(S,[[T,S]|TSs],[T|Ts]) :- % 2: if score matches S, T is in titles
score_list_titles(S,TSs,Ts). % relation must hold for the tails as well
score_list_titles(S,[[T,X]|TSs],Ts) :- % 3: if score
dif(S,X), % doesn't match S, T is not in titles
score_list_titles(S,TSs,Ts). % relation must hold for the tails as well
查询此谓词会产生以下结果:哪些标题的得分分别为100,200和300?
?- score_list_titles(100,[['title1',100],['title2',200],['title3',100]],T).
T = [title1,title3] ? ;
no
?- score_list_titles(200,[['title1',100],['title2',200],['title3',100]],T).
T = [title2] ? ;
no
?- score_list_titles(300,[['title1',100],['title2',200],['title3',100]],T).
T = []
什么分数有什么标题?
?- score_list_titles(S,[['title1',100],['title2',200],['title3',100]],T).
S = 100,
T = [title1,title3] ? ;
S = 200,
T = [title2] ? ;
T = [],
dif(S,100),
dif(S,200),
dif(S,100)
您甚至可以使用if_/3:
更紧凑地表达这种关系score_list_titles(_S,[],[]).
score_list_titles(S,[[T,X]|TSs],TL) :- % if S=X: T is in titles
if_(S=X, TL=[T|Ts], TL=Ts), % otherwise it isn't
score_list_titles(S,TSs,Ts). % relation must hold for the tails as well
这样,在前两个参数被接地(=不包含自由变量)的情况下,谓词甚至不会打开一个不必要的选择点。您可以看到,如果您将以下查询与上述查询进行比较:在上述版本的score_list_titles / 3中,我必须在单个答案后输入;
,以获得没有进一步解决方案的反馈。
?- score_list_titles(100,[['title1',100],['title2',200],['title3',100]],T).
T = [title1,title3]
?- score_list_titles(200,[['title1',100],['title2',200],['title3',100]],T).
T = [title2]
答案 1 :(得分:1)
你做的比你需要的更复杂:
return_title(Score,List,X):-
member([X,Score],List).
然后你可以使用Prolog'所有解决方案'内置,比如findall / 3,或者REPL回溯(在回答后点击';')。