Y have a multidimensional array:
x(0,0) = 1
x(0,1) = 5
x(0,2) = 8
x(1,0) = 3
x(1,1) = 6
x(1,2) = 1
x(2,0) = 2
x(2,1) = 3
x(2,2) = 9
How can I sort the entire matrix taking only the third value (ubound 2) of each?
Y have a multidimensional array:
x(0,0) = 1
x(0,1) = 5
x(0,2) = 8
x(1,0) = 3
x(1,1) = 6
x(1,2) = 1
x(2,0) = 2
x(2,1) = 3
x(2,2) = 9
How can I sort the entire matrix taking only the third value (ubound 2) of each?
Copy those values into a new array and use sortWith?
Yes, I did that, but I thought there could be some function to sort directly without separating the array.
Thanks.
multi dimensional array are not sortable using the array methods built in to Xojo
it would be possible to write a custom sort routine that did though
Could you refactor the multidimensional array as class instances? If so, you can do something like what is described in this blog entry.
This has come up before and except for simple sorting cases I think the in-memory database approach seems to be the better way. You can find a recent discussion on this on the following post: https://forum.xojo.com/55796-sorting-data-array-or-dictionary-with-5-columns
or just pull the specific column values into a one d array
and the row indexes into another
use sortwith on the values then access the specific rows through the indexes array
there are lots of ways to do something like this
new desktop project
in window1.open event I have
Const limit = 199999 Dim r As New random Dim orig(limit,2) As Integer For i As Integer = 0 To limit orig(i,0) = r.inrange(0,limit) orig(i,1) = r.inrange(0,limit) orig(i,2) = r.inrange(0,limit) Next Dim x(limit,2) As Integer For i As Integer = 0 To limit For j As Integer = 0 To 2 x(i,j) = orig(i,j) Next Next // x(0,0) = 1 // x(0,1) = 5 // x(0,2) = 8 // // x(1,0) = 3 // x(1,1) = 6 // x(1,2) = 1 // // x(2,0) = 2 // x(2,1) = 3 // x(2,2) = 9 Dim startTime As Double = Microseconds x.sortBy1(2) Dim endTime As Double = Microseconds Dim elapsed1 As Double = endTime - startTime For i As Integer = 0 To limit For j As Integer = 0 To 2 x(i,j) = orig(i,j) Next Next startTime = Microseconds x.sortBy2(2) endTime = Microseconds Dim elapsed2 As Double = endTime - startTime Break
as well I added a module
in there I put
Public Sub SortBy1(extends arr(, ) as integer, column as integer) Dim rows As Integer = ubound(arr,1) Dim cols As Integer = ubound(arr,2) Dim values() As Integer Dim indexes() As Integer For i As Integer = 0 To rows values.append arr(i, column) indexes.Append i Next values.SortWith indexes Dim newarr(-1,-1) As Integer Redim newarr(rows,cols) For row As Integer = 0 To rows Dim readRow As Integer = indexes(row) For col As Integer = 0 To cols newarr(row,col) = arr(readrow,col) Next Next Redim arr(-1,-1) Redim arr(rows,cols) For row As Integer = 0 To rows For col As Integer = 0 To cols arr(row,col) = newarr(row,col) Next Next End Sub
and
Public Sub SortBy2(extends arr(, ) as integer, column as integer) Dim rows As Integer = ubound(arr,1) Dim cols As Integer = ubound(arr,2) Dim sqlDB As New SQLiteDatabase Call sqlDB.Connect Dim colNames() As String For i As Integer = 0 To cols colNames.append "col" + Str(i) Next Dim sql As String = "create table temp(" + Join(colNames,",") + ")" sqlDB.SQLExecute(sql) sqldb.SQLExecute("begin transaction") For row As Integer = 0 To rows Dim colValues() As String For col As Integer = 0 To cols colValues.append Str(arr(row,col)) Next sql = "insert into temp(" + Join(colNames,",") + ") values (" + Join(colValues,",") + ")" sqlDB.SQLExecute(sql) Next sqldb.SQLExecute("commit transaction") Redim arr(-1,-1) Redim arr(rows,cols) Dim rs As recordset sql= "select * from temp order by " + colNames(column) rs = sqlDB.SQLSelect(sql) Dim row As Integer = 0 While rs <> Nil And rs.eof <> True For col As Integer = 0 To cols arr(row,col) = rs.idxFIeld(col+1).IntegerValue Next row = row + 1 rs.movenext Wend End Sub
the in place in memory version is much faster than the sqlite DB with this data set
BUT it will also use twice as much memory as the original array size