My main problem consist in the creation of a sort function which wolud be used inside SortBy
.
Introduction
The principle of the sort to apply is the following (for a list of points in 2 dimension) :
listosort = {{4, 9}, {-4, -9}, {-5, -7}, {-4, 4}, {-2, -1}, {-6, -9}, {-5, 0}};
SortBy[listosort, {#[[1]], -#[[2]]} &];
We can noticed that :
- The sorting function allows you to sort columns by columns.
- The sorting function is a pure function.
- We can have an ascending or a descending sort with the use of 1 or -1.
Problem
I have to deal with the lists whose dimensions can vary. And I don't want to rewrite the pure function inside SortBy
.
So I wrote the following code :
SPart[x_][y_] := Part[y, x];
ListSPart[x_] := (SPart[#] & /@ (Range@Length@x))*((x) /. {"max" -> 1, "min" -> 0});
SortVDL[x_, y_] := SortBy[x, ListSPart[y]]
So I can write now :
SortVDL[listosort, {1, -1}]
SortVDL[listosort, {"max", "min"}] (*equivalent*)
Instead of writing :
SortBy[listosort, {#[[1]], -#[[2]]} &];
Objectives
It's important to :
- Be able to handle list with elements of n dimensions.
- Be able to choose an ascending or descendand sorting for each column.
- I don't need to treat list of non-numerical value.
Examples of possible writing :
SortVDL[listosort, {1, -1}] (* 2D *)
SortVDL[listosort, {1, 1}] (* 2D *)
SortVDL[listosort, {1, -1, 1, 1}] (* 4D *)
Question
My code unfortunately does not work.
Indeed, the following lines of code :
SortVDL[listosort, {1, 1}];
SortBy[listosort, {#[[1]], #[[2]]} &];
SortVDL[listosort, {-1, 1}];
SortBy[listosort, {-#[[1]], #[[2]]} &];
SortVDL[listosort, {-1, -1}];
SortBy[listosort, {-#[[1]], -#[[2]]} &];
are not equivalent.
SortVDL seems to always give the same result. Why ?
Is there a method to automatically generate reliable pure functions ?
Resume
Code n°1
F11[x_][y_] := Part[y, x];
F1[x_] := (F11[#] & /@ (Range@Length@x))*x;
F1[{1, -1, 1}];
Code n°2
F2[x_] := Function[Evaluate[Thread[F1[x] Slot /@ (ConstantArray[1, Length@x])]]];
F2[{1, -1, 1}];
Code n°3 (Xavier's answer)
F3[x_] := Activate[(Evaluate[x*Table[Inactive[Part][#, i], {i, Length@x}]]) &];
F3[{1, -1, 1}];
Code n°1 >> Don't work with SortBy
>> See Xavier's answer.
Code n°2 >> Don't work with SortBy
>> See Xavier's answer.
Code n°3 >> Work with SortBy
>> See Xavier's answer.
Final Answer
Xavier's answer :
mySort[list_, coef_] :=
SortBy[list,
Activate[(Evaluate[
coef Table[
Inactive[Part][#, i], {i, Dimensions[list][[2]]}]]) &]];
Ciao's answer :
numColSorter[list_, sortord_] :=
list[[Ordering[Transpose[Transpose[list]*sortord]]]];
Benchmarks :
data1 = RandomInteger[{-9, 9}, {10^6, 2}];
mySort
>> 0.733489 s
numColSorter
>> 0.282189 s