Thread overview | |||||||||
---|---|---|---|---|---|---|---|---|---|
|
June 07, 2014 How to sort a 2D array by column | ||||
---|---|---|---|---|
| ||||
I have a dynamic array of dynamic array of strings I want to sort the outer array based on specific columns of the inner array This is how I am populating the 2D array void readFromFile() { alias Row = string[]; alias Table = Row[]; Row the_row; Table the_table; auto inFile = File("sample.txt", "r"); auto temp = chomp(inFile.readln()); // skip header while (!inFile.eof()) { string row_in = chomp(inFile.readln()); the_row = split(row_in,"\t"); the_table ~= the_row; } writeln(the_table.length); the_table.sort; // I believe this sort uses all the columns inside the_row. What I want is use specific column(s) } This is my attemot to create a compare object. But I don't know how to use it together with .sort member function class RowCompare { int[] m_columns; this(int[] columns) { m_columns = m_columns; } int opCmp()(ref const Row lhs, ref const Row rhs) const { for (auto i = 0; i < m_columns.length; ++i) { ref const auto currentColumn = m_columns[i]; if (lhs[currentColumn] < rhs[currentColumn] ) return true; if (rhs[currentColumn] < lhs[currentColumn] ) return false; } } } |
June 07, 2014 Re: How to sort a 2D array by column | ||||
---|---|---|---|---|
| ||||
Posted in reply to katuday | > This is my attemot to create a compare object. But I don't know how to use it together with .sort member function Don't use the .sort property. Use std.algorithm.sort, which has a "less" predicate (that should return a bool). http://dlang.org/phobos/std_algorithm.html#sort |
June 07, 2014 Re: How to sort a 2D array by column | ||||
---|---|---|---|---|
| ||||
Posted in reply to Chris Cain | On Saturday, 7 June 2014 at 19:14:01 UTC, Chris Cain wrote:
>> This is my attemot to create a compare object. But I don't know how to use it together with .sort member function
>
>
> Don't use the .sort property. Use std.algorithm.sort, which has a "less" predicate (that should return a bool).
>
> http://dlang.org/phobos/std_algorithm.html#sort
Also note that the examples use a string to define the predicate, but it accepts functions as well. Such as:
bool myCompareFunc(AType lhs, AType rhs)
{
return lhs.blah < rhs.blah;
}
//...
AType[] arr;
//...
arr.sort!myCompareFunc();
|
June 07, 2014 Re: How to sort a 2D array by column | ||||
---|---|---|---|---|
| ||||
Posted in reply to Chris Cain | On 06/07/2014 12:18 PM, Chris Cain wrote:
> Also note that the examples use a string to define the predicate, but it
> accepts functions as well. Such as:
>
> bool myCompareFunc(AType lhs, AType rhs)
> {
> return lhs.blah < rhs.blah;
> }
>
> //...
> AType[] arr;
> //...
> arr.sort!myCompareFunc();
Just for completeness, lambdas as well:
arr.sort!((a, b) => a.blah < b.blah);
Ali
|
June 07, 2014 Re: How to sort a 2D array by column | ||||
---|---|---|---|---|
| ||||
Posted in reply to katuday | On Saturday, 7 June 2014 at 19:06:10 UTC, katuday wrote:
> the_table.sort; // I believe this sort uses all the columns inside the_row. What I want is use specific column(s)
Supposing you use the *function* "std.algorithm.sort", then that is going to sort you rows according to the (default) predicate "<".
In this case, "<" means lexicographical comparison for arrays. EG: compares the first element, then the second, then the third, until 2 are different.
I don't have your input, but here is an example program:
import std.stdio, std.algorithm, std.random;
//----
void main()
{
int[][] arr = new int[][](10, 10);
foreach(i; 0 .. 10)
foreach(j; 0 .. 10) {
arr[i][j] = rndGen().front % 5;
rndGen().popFront();
}
writefln("%(%s\n%)", arr.sort()); //Note the "()": Very important.
}
//----
[0, 1, 0, 0, 0, 0, 2, 3, 1, 1]
[0, 4, 4, 1, 2, 3, 4, 2, 1, 0] </--
[0, 4, 4, 1, 3, 4, 0, 2, 3, 3] </--
[2, 0, 0, 4, 1, 3, 3, 4, 2, 4]
[2, 0, 4, 3, 3, 0, 2, 4, 2, 1]
[3, 1, 2, 1, 1, 4, 1, 4, 1, 2]
[3, 3, 2, 1, 0, 4, 0, 2, 3, 2]
[4, 0, 0, 4, 3, 0, 4, 3, 4, 2]
[4, 2, 1, 1, 1, 2, 0, 1, 2, 2]
[4, 4, 3, 2, 2, 1, 1, 0, 4, 2]
//----
As you can see here, this was ordered by looking up to 5 elements deep.
If you need something more customize, you can do it by specifying your own function. For example, according to each row's Euclidean norm:
//----
bool compare(int[] lhs, int[] rhs) {
auto a = reduce!"a += b^2"(0, lhs);
auto b = reduce!"a += b^2"(0, rhs);
return a < b;
}
void main()
{
int[][] arr = new int[][](10, 4);
foreach(i; 0 .. 10)
foreach(j; 0 .. 4) {
arr[i][j] = rndGen().front % 9 - 4;
rndGen().popFront();
}
writefln("%(%2s\n%)", arr.sort!compare);
}
//----
[-2, -3, -1, 3]
[ 4, -2, -2, -2]
[-2, 0, 2, -4]
[ 3, -2, -4, 1]
[ 3, -2, 2, 3]
[-2, 3, 3, 0]
[ 1, 2, 0, -2]
[ 4, 2, -1, 0]
[ 2, 1, 1, 3]
[ 3, 3, 3, 4]
//----
In the above examples, I used numbers, but the language really doesn't care, as long as your elements have strict total ordering according to the predicate you have used.
|
June 07, 2014 Re: How to sort a 2D array by column | ||||
---|---|---|---|---|
| ||||
Posted in reply to Chris Cain | On Saturday, 7 June 2014 at 19:18:34 UTC, Chris Cain wrote: > On Saturday, 7 June 2014 at 19:14:01 UTC, Chris Cain wrote: >>> This is my attemot to create a compare object. But I don't know how to use it together with .sort member function >> >> >> Don't use the .sort property. Use std.algorithm.sort, which has a "less" predicate (that should return a bool). >> >> http://dlang.org/phobos/std_algorithm.html#sort > > Also note that the examples use a string to define the predicate, but it accepts functions as well. Such as: > > bool myCompareFunc(AType lhs, AType rhs) > { > return lhs.blah < rhs.blah; > } > > //... > AType[] arr; > //... > arr.sort!myCompareFunc(); I need an example if you don't mind. My sort function requires columns numbers supplied at run-time This is how I defined my sort function bool compareRow(int[] columns, ref const Row lhs, ref const Row rhs) { bool ret = false; for (auto i = 0; i < columns.length; ++i) { const auto currentColumn = columns[i]; if (lhs[currentColumn] < rhs[currentColumn] ) ret = true; if (rhs[currentColumn] < lhs[currentColumn] ) ret = false; } return ret; } Calling sort like this does not compile sort!(compareRow)(sort_key,the_table); |
June 07, 2014 Re: How to sort a 2D array by column | ||||
---|---|---|---|---|
| ||||
Posted in reply to katuday | On Saturday, 7 June 2014 at 20:47:31 UTC, katuday wrote: > On Saturday, 7 June 2014 at 19:18:34 UTC, Chris Cain wrote: >> On Saturday, 7 June 2014 at 19:14:01 UTC, Chris Cain wrote: >>>> This is my attemot to create a compare object. But I don't know how to use it together with .sort member function >>> >>> >>> Don't use the .sort property. Use std.algorithm.sort, which has a "less" predicate (that should return a bool). >>> >>> http://dlang.org/phobos/std_algorithm.html#sort >> >> Also note that the examples use a string to define the predicate, but it accepts functions as well. Such as: >> >> bool myCompareFunc(AType lhs, AType rhs) >> { >> return lhs.blah < rhs.blah; >> } >> >> //... >> AType[] arr; >> //... >> arr.sort!myCompareFunc(); > > I need an example if you don't mind. My sort function requires columns numbers supplied at run-time > > This is how I defined my sort function > bool compareRow(int[] columns, ref const Row lhs, ref const Row rhs) > { > bool ret = false; > for (auto i = 0; i < columns.length; ++i) > { > const auto currentColumn = columns[i]; > if (lhs[currentColumn] < rhs[currentColumn] ) > ret = true; > if (rhs[currentColumn] < lhs[currentColumn] ) > ret = false; > } > return ret; > } That function don't make no sense (to me): It'll just return the result of the last iteration. It *looks* like you are trying to do a lexicographical comparison? You should just replace those "ret = XXX" with straight up "return XXX". The last "return ret" should be "return false" (I think) > Calling sort like this does not compile > > sort!(compareRow)(sort_key,the_table); You need to create a delegate that binds your sort key to have predicate that accepts exactly 2 arguments. A lambda will fill that role. sort!((lhs, rhs)=>compareRow(sort_key, a, b))(the_table); or (not tested) use std.functional's curry: sort!(curry!(compareRow, sort_key))(the_table); |
Copyright © 1999-2021 by the D Language Foundation