在prolog中对原子进行排序

时间:2013-07-13 14:05:57

标签: list sorting prolog

我的知识库中有以下格式的原子:

car_details(bmw, [1, 3, 5], 40000).
car_details(audi, [1, 3, 4, 5, 6, 8], 60000).
car_details(volvo, [40, 60, 80, 90], 50000).
car_details(mercedes, [a, b, c, e, s], 80000).

我正在尝试根据成本(第三位置值)对这些原子进行排序。是否有内置的谓词可以让我这样做?我尝试将sort/2findall谓词一起使用。但是,这只会产生所有成本的排序列表。我也想要它的相关信息。

上述预期结果应采用以下格式:

[[bmw, [1, 3, 5], 40000], [volvo, [40, 60, 80, 90], 50000], [audi, [1, 3, 4, 5, 6, 8], 60000], [mercedes, [a, b, c, e, s], 80000]].

2 个答案:

答案 0 :(得分:1)

我认为没有一个谓词可以做到,但一个简单的解决方案可能是:

reorder([], []).
reorder([[P,M,I]|W], [[M,I,P]|W1]) :- reorder(W, W1).

cars_by_price(Result) :-
    setof([Price, Make, Items], car_details(Make, Items, Price), L),
    reorder(L, Result).

setof谓词将删除重复项,因此我假设您的数据集是唯一的。如果没有,您可能需要执行findall并在sort之前执行reorder

答案 1 :(得分:1)

在引入comp_prices / 3后,

predsort / 3可以工作:

comp_prices(R,[_,_,P1],[_,_,P2]) :- compare(R,P1,P2).

?- findall([M,D,P],car_details(M,D,P),L), predsort(comp_prices,L,S).
L = [[bmw, [1, 3, 5], 40000], [audi, [1, 3, 4, 5, 6|...], 60000], [volvo, [40, 60, 80, 90], 50000], [mercedes, [a, b, c|...], 80000]],
S = [[bmw, [1, 3, 5], 40000], [volvo, [40, 60, 80, 90], 50000], [audi, [1, 3, 4, 5|...], 60000], [mercedes, [a, b, c|...], 80000]].

keysort / 2效率更高,使用库(pairs)它也很方便使用:

4 ?- findall(P-[M,D,P],car_details(M,D,P), L), keysort(L, S), pairs_values(S, T).
L = [40000-[bmw, [1, 3, 5], 40000], 60000-[audi, [1, 3, 4, 5|...], 60000], 50000-[volvo, [40, 60, 80|...], 50000], 80000-[mercedes, [a, b|...], 80000]],
S = [40000-[bmw, [1, 3, 5], 40000], 50000-[volvo, [40, 60, 80, 90], 50000], 60000-[audi, [1, 3, 4|...], 60000], 80000-[mercedes, [a, b|...], 80000]],
T = [[bmw, [1, 3, 5], 40000], [volvo, [40, 60, 80, 90], 50000], [audi, [1, 3, 4, 5|...], 60000], [mercedes, [a, b, c|...], 80000]].