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