Sort multidimensional array by one of their values

  1. 5 weeks ago
    Edited 5 weeks ago

    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?

  2. Markus W

    Sep 16 Pre-Release Testers #JeSuisHuman New Zealand, Auc...

    Copy those values into a new array and use sortWith?

  3. Yes, I did that, but I thought there could be some function to sort directly without separating the array.
    Thanks.

  4. Norman P

    Sep 16 Pre-Release Testers, Xojo Pro great-white-software.com/blog

    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

  5. Douglas H

    Sep 16 Pre-Release Testers, Xojo Pro

    Could you refactor the multidimensional array as class instances? If so, you can do something like what is described in this blog entry.

  6. 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

  7. Norman P

    Sep 17 Pre-Release Testers, Xojo Pro great-white-software.com/blog

    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

  8. Norman P

    Sep 17 Pre-Release Testers, Xojo Pro great-white-software.com/blog

    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

or Sign Up to reply!