首页 > 解决方案 > 创建键值对列表

问题描述

我有这些事实:

name(john),
name(mary),
name(jack),

当我“迭代”所有事实时,我会为每个名称找到类似于评级(一个数字)的东西。我希望该评级与 2-john 或 john-2 之类的名称配对,将它们存储在列表中并根据数字对列表进行排序。我怎样才能在 ProLog 中做到这一点?

name(PersonsName), findRating(PersonsName, Rating), fail.

标签: listsortingprologkey

解决方案


@false 在评论中给出了正确答案:

setof(V-K, ( name(K), rating(K, V) ), VKs)

@false 的个人笑话,不止:-. :)

我将在这里为那些需要缺失部分的人进行扩展。

首先,事实必须是事实,即

name(john), 不是事实,因为它以 a 结尾,。事实需要以句点 ( .) 结束。

需要下一个事实来将评级与该人相关联。

rating(john,2).
rating(mary,3).
rating(jack,4).

现在为setof/3

setof/3 的签名是setof(+Template, +Goal, -Set)

Goal是将返回所需数据的查询,在这种情况下,目标name(K), rating(K,V)()( name(K), rating(K, V) )

示例运行:

?- name(Name),rating(Name,Rating).
Name = john,
Rating = 2 ;
Name = mary,
Rating = 3 ;
Name = jack,
Rating = 4.

虽然这为我们提供了所需的数据,但它并不是一种有用的格式并一个一个地返回结果。

Template是结果中数据的格式,在这种情况下V-K,其中VforValue是评分,KforKey是键。结果会是这样2-john

这是到目前为止我们通过查询和示例运行演示的示例:

rating(V-K) :-
    name(K),
    rating(K,V).

?- rating(Ratings).
Ratings = 2-john ;
Ratings = 3-mary ;
Ratings = 4-jack.

请注意,结果以正确的格式返回,但仍不在列表中。

Set是收集到结果中的内容。

由于您要求排序结果,setof/3因此使用而不是bagof/3. 如中所述setof/3sorts the result using sort/2 to get a sorted list of alternatives without duplicates.

为了更容易运行查询而不是每次都输入整个 setof/3,只需将其放入谓词中即可。

ratings(VKs) :-
    setof(V-K,(name(K),rating(K,V)),VKs).

完整的代码。

name(john).
name(mary).
name(jack).

rating(john,2).
rating(mary,3).
rating(jack,4).

ratings(VKs) :-
    setof(V-K,(name(K),rating(K,V)),VKs).

示例运行:

?- ratings(VKs).
VKs = [2-john, 3-mary, 4-jack].

注意:这也可以使用library(assoc): Association lists来完成,但是对于这个问题,使用setof/3更加简洁。


推荐阅读