Thread overview | |||||||
---|---|---|---|---|---|---|---|
|
August 18, 2020 How to sort a multidimensional ndslice? | ||||
---|---|---|---|---|
| ||||
I want to sort a two-dimensional ndslice by its columns according to some predefined predicate. What I mean is _not_ sorting the contents of each column individually, but instead to reorder the entire columns of the matrix so that they are sorted according to some "greater than" function. Here's a MWE (the `larger` function is just an example): ``` import std.stdio; import mir.ndslice.slice; import mir.ndslice.sorting; void main() { auto a = [[1, -1, 3, 2], [0, -2, 3, 1]].sliced; writeln(a); a.byDim!1.sort!((u, v) => larger(u, v)); writeln(a); } auto larger(C)(C u, C v) { import mir.math.sum : sum; return sum(u) > sum(v); } ``` I would have expected this to print: [[1, -1, 3, 2], [0, -2, 3, 1]] [[3, 2, 1, -1], [3, 1, 0, -2]] but instead it prints [[1, -1, 3, 2], [0, -2, 3, 1]] [[1, -1, 3, 2], [0, -2, 3, 1]] i.e, nothing happens! Any suggestions? Arredondo. |
August 18, 2020 Re: How to sort a multidimensional ndslice? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Arredondo | The following code just sorts each row: ------ /+dub.sdl: dependency "mir-algorithm" version="~>3.9.24" +/ import mir.ndslice; import mir.ndslice.sorting; import mir.algorithm.iteration: each; void main() { // fuse, not sliced if you use an array of arrays for argument auto a = [[1, -1, 3, 2], [0, -2, 3, 1]].fuse; // make an index a.byDim!0.each!(sort!larger); import std.stdio; writeln(a); // [[3, 2, 1, -1], [3, 1, 0, -2]] } auto larger(C)(C u, C v) { return u > v; } ------ To reorder the columns data according to precomputed index: ------ /+dub.sdl: dependency "mir-algorithm" version="~>3.9.24" +/ import mir.ndslice; import mir.series; import mir.ndslice.sorting; import mir.algorithm.iteration: each; import mir.math.sum; void main() { // fuse, not sliced if you use an array of arrays for argument auto a = [[1, -1, 3, 2], [0, -2, 3, 1]].fuse; // make an index auto index = a.byDim!1.map!sum.slice; auto s = index.series(a.transposed); auto indexBuffer = uninitSlice!int(s.length); auto dataBuffer = uninitSlice!int(s.length); sort!larger(s, indexBuffer, dataBuffer); import std.stdio; writeln(a); /// [[3, 2, 1, -1], [3, 1, 0, -2]] } auto larger(C)(C u, C v) { return u > v; } ----- |
August 18, 2020 Re: How to sort a multidimensional ndslice? | ||||
---|---|---|---|---|
| ||||
Posted in reply to 9il | On Tuesday, 18 August 2020 at 04:07:56 UTC, 9il wrote:
> To reorder the columns data according to precomputed index:
> auto index = a.byDim!1.map!sum.slice;
Hello Ilya, thanks for the answer!
Unfortunately I can't use it because I don't have (and can't define) a sorting index for my columns. I only have a predicate `larger(c1, c2)` that compares two columns to decide which one is "larger".
Cheers!
Armando.
|
August 18, 2020 Re: How to sort a multidimensional ndslice? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Arredondo | On Tuesday, 18 August 2020 at 13:07:56 UTC, Arredondo wrote: > On Tuesday, 18 August 2020 at 04:07:56 UTC, 9il wrote: >> To reorder the columns data according to precomputed index: >> auto index = a.byDim!1.map!sum.slice; > > Hello Ilya, thanks for the answer! > > Unfortunately I can't use it because I don't have (and can't define) a sorting index for my columns. I only have a predicate `larger(c1, c2)` that compares two columns to decide which one is "larger". > > Cheers! > Armando. Armando, I believe you can just pass your predicate to the sort! template http://docs.algorithm.dlang.io/latest/mir_ndslice_sorting.html |
August 19, 2020 Re: How to sort a multidimensional ndslice? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Arredondo | On Tuesday, 18 August 2020 at 13:07:56 UTC, Arredondo wrote:
> On Tuesday, 18 August 2020 at 04:07:56 UTC, 9il wrote:
>> To reorder the columns data according to precomputed index:
>> auto index = a.byDim!1.map!sum.slice;
>
> Hello Ilya, thanks for the answer!
>
> Unfortunately I can't use it because I don't have (and can't define) a sorting index for my columns. I only have a predicate `larger(c1, c2)` that compares two columns to decide which one is "larger".
>
> Cheers!
> Armando.
This should work. But reallocates the data.
/+dub.sdl:
dependency "mir-algorithm" version="~>3.9.24"
+/
import std.stdio;
import mir.array.allocation;
import mir.ndslice;
import mir.ndslice.sorting;
void main() {
auto a = [[1, -1, 3, 2],
[0, -2, 3, 1]].fuse;
writeln(a);
auto b = a.byDim!1.array;
b.sort!larger;
auto c = b.fuse!1;
writeln(c);
}
auto larger(C)(C u, C v) {
import mir.math.sum : sum;
return sum(u) > sum(v);
}
|
Copyright © 1999-2021 by the D Language Foundation