从列表列表中返回元素 - prolog

时间:2016-06-08 18:27:39

标签: list prolog

我有一个包含标题和分数的列表列表,如:[ [ '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.

但它没有工作......关于另一个实现的任何想法?

2 个答案:

答案 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回溯(在回答后点击';')。