2

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

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/2谓词findall。但是,这只会导致所有成本的排序列表。我也想要相关的信息。

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

[[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]].

4

2 回答 2

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需要sortreorder.

于 2013-07-13T14:27:09.740 回答
1

predsort /3 可以工作,在引入 comp_prices/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 效率更高,使用 library( 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]].
于 2013-07-13T16:26:48.167 回答