Reputation: 1055
In SWI-Prolog there is the predicate sort/2 to sort lists. Is there a good way to sort a list of list with fixed length by some index. I mean in example, if I have the following list of elements
[[1,2], [3,1], [2, 5]]
Is there a function in SWI-Prolog to sort it by first or second index. By first index the result would be:
[[1,2], [2,5], [3, 1]]
By second index:
[[3,1], [1,2], [2, 5]]
Upvotes: 1
Views: 531
Reputation: 18726
The efficient and portable way to get what you want goes like this:
map each element X
of the original list to a pair I-X
, where I
is the value to sort by.
use keysort/2
on the resulting list; note that keysort/2
preserves duplicate items.
at last, get rid of the values of I
in the sorted list—we don't need them anymore.
The above directly translates to the predicate lists_sortedBySecondItem/2
:
lists_sortedBySecondItem(Ess,Xss) :- maplist(list_pair,Ess,Pairs), % (1) keysort(Pairs,Sorted), % (2) maplist(pair_second,Sorted,Xss). % (3) list_pair(Xs,I-Xs) :- nth(2,Xs,I). pair_second(_-X,X).
Sample query using GNU Prolog 1.5.0:
| ?- lists_sortedBySecondItem([[1,2],[3,1],[2,5]], Xss). Xss = [[3,1],[1,2],[2,5]] yes
Upvotes: 2
Reputation: 4456
Can use https://www.swi-prolog.org/pldoc/doc_for?object=predsort/3 if removing duplicates is OK:
test(Nth1, S) :-
L = [[1,2], [3,1], [2, 5], [1,2]],
predsort(nth1_compare(Nth1), L, S).
nth1_compare(Nth1, Comp, L1, L2) :-
nth1(Nth1, L1, V1),
nth1(Nth1, L2, V2),
compare(Comp, V1, V2).
Results:
?- test(1, S).
S = [[1,2],[2,5],[3,1]].
?- test(2, S).
S = [[3,1],[1,2],[2,5]].
Upvotes: 1