Reputation: 1322
I have atoms of the following format in my knowledge base:
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).
I am trying to sort these atoms based on their costs (3rd position values). Is there a built in predicate which can allow me to do that? I've tried using sort/2
with the findall
predicate. However, that only results in a sorted list of all the costs. I want the associated information with it too.
The expected result from the above should be of the following format:
[[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]].
Upvotes: 2
Views: 422
Reputation: 60024
predsort/3 could work, after introducing 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 is more efficient, with library(pairs) it's also handy to use:
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]].
Upvotes: 1
Reputation: 58254
I don't think there's one predicate to do it, but a simple solution might be:
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).
The setof
predicate will remove duplicates, so I'm assuming that your sets of data are unique. If not, you may need to do the findall
and do a sort
right before the reorder
.
Upvotes: 1