@ false дал правильный ответ в комментарии:
setof(V-K, ( name(K), rating(K, V) ), VKs)
Личная сторонняя шутка для @false, которая была больше :-
.:)
Я просто расширю это здесь для тех, кому нужны недостающие части.
Сначала факты должны быть фактами, то есть
name(john),
не являетсяфакт, потому что это заканчивается ,
.Факт должен заканчиваться точкой (.
).
Следующие факты необходимы, чтобы связать рейтинг с человеком.
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
, где V
для Value
- рейтинг, а K
для Key
это ключ.Результат будет выглядеть так: 2-john
.
Вот пример того, что мы продемонстрировали с помощью запроса и примера:
rating(V-K) :-
name(K),
rating(K,V).
?- rating(Ratings).
Ratings = 2-john ;
Ratings = 3-mary ;
Ratings = 4-jack.
Обратите внимание, что результаты возвращаются вправильный формат, но все еще отсутствует в списке.
Set
- это то, что собрано в результат.
Поскольку вы запросили отсортированный результат, вместо bagof/3
используется setof/3
.Как отмечено в setof/3
: sorts the result using sort/2 to get a sorted list of alternatives without duplicates.
Чтобы упростить выполнение запроса вместо того, чтобы каждый раз набирать весь набор / 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].
Примечание. Это также можно сделать с помощью библиотеки (assoc):Списки ассоциаций , но для этой проблемы использование setof/3
гораздо более кратко.