Hello everybody
please, is there someone who can teach me How can I sort a list of functors based on the fourth atom? For instance, if I have the following list[p('a', 2.5, 2, 4), p('b', 7.5, 3, 1)], then the sorted copy of this list, in ascending order, would be [p('b', 7.5, 3, 1), p('a', 2.5, 2, 4)].
-
- VIP Member
- Posts: 68
- Joined: 5 Oct 2011 15:16
Re: Sort a List of Functors
Generally, define your own COMPARATOR and use list::sortBy/2 or list::sortBy/3.
Usually, it's enough "meaningful" functor and list::sort/1 or list::sort/2.
Usually, it's enough "meaningful" functor and list::sort/1 or list::sort/2.
-
- VIP Member
- Posts: 458
- Joined: 5 Nov 2000 0:01
Re: Sort a List of Functors
Here's an example you can test for yourself as a console application.
Code: Select all
domains
pTerm = p(integer, integer, integer, integer).
clauses
run() :-
PTerms = [p(1, 2, 3, 4), p(3, 2, 1, 0), p(6, 3, 1, 2), p(2, 5, 7, 8)],
ValueN =
{ (Index, P) = I :-
p(A, B, C, D) = P,
I = list::nth(Index, [A, B, C, D])
},
Pos = 2, % Note: a 0-based index is used in the ValueN anonymous predicate
SortedPTerms = list::sortBy({ (L, R) = compare(ValueN(Pos, L), ValueN(Pos, R)) }, PTerms),
%
stdio::write("\n\nUNSORTED"),
foreach p(A, B, C, D) in PTerms do
stdio::writef("\n%,%,%,%", A, B, C, D)
end foreach,
stdio::write("\n\nSORTED on position index (0...N)", Pos),
foreach p(A, B, C, D) in SortedPTerms do
stdio::writef("\n%,%,%,%", A, B, C, D)
end foreach,
!,
_ = readline().
-
- VIP Member
- Posts: 68
- Joined: 5 Oct 2011 15:16
Re: Sort a List of Functors
Code: Select all
domains
pTerm = p(integer, integer, integer, integer).
clauses
run() :-
PTerms = [p(6, 3, 1, 3), p(1, 2, 3, 4), p(3, 2, 1, 0), p(6, 3, 1, 2), p(2, 5, 7, 8)],
Count = varM::new(0),
ValueN =
{ (Index, P) = I :-
p(A, B, C, D) = P,
I = list::nth(Index, [A, B, C, D]),
Count:value := Count:value + 1
},
Pos = 2, % Note: a 0-based index is used in the ValueN anonymous predicate
Sorted1 = list::sortBy({ (L, R) = compare(ValueN(Pos, L), ValueN(Pos, R)) }, PTerms),
console::write(Sorted1, "... ", Count:value),
Count:value := 0,
Sorted2 = sortByFun(PTerms, {(X) = ValueN(Pos, X)}, core::ascending),
console::write("\n", Sorted2, "... ", Count:value),
console::write("\n........................................."),
_ = console::readLine().
class predicates
sortByFun : (Elem1*, core::function{Elem1, Elem2}, core::sortOrder) -> Elem1*.
clauses
sortByFun(ListIn, Fun, Order) = ListOut :-
ToSort = list::map(ListIn, {(Lj) = core::tuple(Fun(Lj), Lj)}),
Sorted = list::sort(ToSort, Order),
ListOut = list::map(Sorted, {(core::tuple(_, B)) = B}).
[p(6,3,1,3),p(3,2,1,0),p(6,3,1,2),p(1,2,3,4),p(2,5,7,8)]... 20
[p(3,2,1,0),p(6,3,1,2),p(6,3,1,3),p(1,2,3,4),p(2,5,7,8)]... 5
.........................................
-
- VIP Member
- Posts: 1466
- Joined: 28 Feb 2000 0:01
Re: Sort a List of Functors
If you just need a hardcoded sorting then it could look like this (assuming that the domain only contains the p functor):
Or your can "short-circuit" by using an anonymous predicate
Code: Select all
class predicates
sort4 : (pDom* L) -> pDom* S.
clauses
sort4(L) = list::sortBy(compare4, L).
class predicates
compare4 : comparator{pDom}.
clauses
compare4(p(_, _, _, A), p(_, _, _, B)) = compare(A, B).
Code: Select all
class predicates
sort4 : (pDom* List) -> pDom* Sort4.
clauses
sort4(L) = list::sortBy({ (p(_, _, _, A), p(_, _, _, B)) = compare(A, B) }, L).
Regards Thomas Linder Puls
PDC
PDC
-
- VIP Member
- Posts: 68
- Joined: 5 Oct 2011 15:16
Re: Sort a List of Functors
Code: Select all
domains
pTerm = p(integer, integer, integer, integer).
clauses
run() :-
T1 = p(6, 3, 1, 3), T2 = p(3, 2, 1, 3), T3 = p(2, 5, 7, 3),
L1 = [ T1, T2, T3 ], L2 = [ T2, T1, T3 ], L3 = [ T3, T2, T1 ], L4 = [ T2, T3, T1 ],
foreach L in [ L1, L2, L3, L4 ] do
Sorted = list::sortBy(compare4, L),
console::write(Sorted, "\n")
end foreach,
console::write("........................................."),
_ = console::readLine().
class predicates
compare4 : comparator{pTerm}.
clauses
compare4(p(_, _, _, A), p(_, _, _, B)) = compare(A, B).
Several lists containing exactly the same elements (the same set) ordered by the same sorting.[p(6,3,1,3),p(3,2,1,3),p(2,5,7,3)]
[p(3,2,1,3),p(6,3,1,3),p(2,5,7,3)]
[p(2,5,7,3),p(3,2,1,3),p(6,3,1,3)]
[p(3,2,1,3),p(2,5,7,3),p(6,3,1,3)]
.........................................
Hm...
I don't know why, but I would prefer:
Code: Select all
class predicates
compare4 : comparator{pTerm}.
clauses
compare4(p(_, _, _, A), p(_, _, _, B)) = compare(A, B) :-
A <> B,
!.
compare4(A, B) = compare(A, B).
-
- VIP Member
- Posts: 1466
- Joined: 28 Feb 2000 0:01
Re: Sort a List of Functors
Yes, I agree on that. And if you intend to use the comparator in a map or set, it is crucial that the comparison covers all values.
Notice that now you can write:
Or as an anonymous predicate:
compareNotEqual is a predicate in core
Notice that now you can write:
Code: Select all
clauses
compare4(p(_, _, _, A4 | A), p(_, _, _, B4 | B)) = compareNotEqual(A4, B4) otherwise compare(A, B).
Code: Select all
clauses
sort4(L) =
list::sortBy(
{ (p(_, _, _, A4 | A), p(_, _, _, B4 | B)) =
compareNotEqual(A4, B4)
otherwise compare(A, B) %
},
L).
Regards Thomas Linder Puls
PDC
PDC
-
- VIP Member
- Posts: 68
- Joined: 5 Oct 2011 15:16
Re: Sort a List of Functors
Thank you for all this "new words".
This is interesting.
I have "old words" additions:
core +
list +
So, our example:
By the way, it used to be in VIP's class list some predicate sortEq once...
Or I'm mistaken?!)))
This is interesting.
I have "old words" additions:
core +
Code: Select all
predicates
compareBF : (Value Left, Value Right, function{Value, ToCompare}) -> compareResult.
Code: Select all
clauses
compareBF(L, R, CF) = compare(tuple(CF(L), L), tuple(CF(R), R)).
Code: Select all
predicates
sortBF : (Elem*, function{Elem, ToCompare}) -> Elem*.
sortBF : (Elem*, function{Elem, ToCompare}, sortOrder) -> Elem*.
Code: Select all
clauses
sortBF(L, CF) = sortBF(L, CF, ascending).
sortBF(L, CF, Order) = sortBy({(A, B) = compareBF(A, B, CF)}, L, Order).
Code: Select all
Sorted = list::sortBF(List, {(p(_, _, _, V)) = V})
Or I'm mistaken?!)))