Results 1 to 13 of 13

Thread: [RESOLVED] Sort multidimensional array

  1. #1

    Thread Starter
    Lively Member
    Join Date
    Sep 2006
    Posts
    91

    Resolved [RESOLVED] Sort multidimensional array

    peace

    The array is 4 dimensions Ar(A,B,C,D)=X
    all values(A,B,C,D and X) are integers >= 0 (decimal not allowed )
    I need to sort that array (descending) by the value of X
    then reorder A

    an example

    before sorting

    Ar(0,5,1,0)=3
    Ar(1,6,1,10)=7
    Ar(2,7,1,5)=1
    Ar(3,8,1,5)=10

    After sorting

    Ar(0,8,1,5)=10
    Ar(1,6,1,10)=7
    Ar(2,5,1,0)=3
    Ar(3,7,1,5)=1

    that's all

    thanks for help
    Last edited by Khalefa...@; Nov 27th, 2010 at 07:58 PM.

  2. #2
    PowerPoster Code Doc's Avatar
    Join Date
    Mar 2007
    Location
    Omaha, Nebraska
    Posts
    2,354

    Re: Sort multidimensional array

    This seems sloppy but does it. Build a form with a command button and a list box with the Sorted property set to true. Then apply this code:
    Code:
    Private Sub Command1_Click()
    Dim Ar(3, 8, 1, 10) As Integer, N As Integer, Xr(3, 8, 1, 10) As Integer
    Ar(0, 5, 1, 0) = 3
    Ar(1, 6, 1, 10) = 7
    Ar(2, 7, 1, 5) = 1
    Ar(3, 8, 1, 5) = 10
    For I = 0 To 3
        For J = 5 To 8
            For K = 1 To 1
                For L = 0 To 10
                    If Ar(I, J, K, L) Then List1.AddItem Format$(Ar(I, J, K, L), "00")
                Next
            Next
        Next
    Next
    For M = List1.ListCount - 1 To 0 Step -1
        For I = 0 To 3
            For J = 5 To 8
                For K = 1 To 1
                    For L = 0 To 10
                        If Ar(I, J, K, L) = Val(List1.List(M)) Then
                           Xr(N, J, K, L) = Ar(I, J, K, L)
                           N = N + 1
                        End If
                    Next
                Next
            Next
        Next
    Next
    For I = 0 To 3
        For J = 5 To 8
            For K = 1 To 1
                For L = 0 To 10
                    If Xr(I, J, K, L) Then Ar(I, J, K, L) = Xr(I, J, K, L)
                Next
            Next
        Next
    Next
    End Sub
    Pardon the simplicity of using the sorted list box, but I could not resist.
    Regardless, this should get a discussion started on how to do it simpler and perhaps without using a slave arrray of equal dimensions. Note that I looped only through the defined value dimensions to help speed it up a little. Good problem. Multi-dimensional arrays are always a challenge.
    Last edited by Code Doc; Nov 26th, 2010 at 12:08 AM.
    Doctor Ed

  3. #3

    Thread Starter
    Lively Member
    Join Date
    Sep 2006
    Posts
    91

    Re: Sort multidimensional array

    Thanks I appreciate your reply
    but it seems very slow specially when using a ListBox
    the sorting process is a small part loops thousands times within a large process
    Note that above values are totally random values not fixed at all

    thanks again

  4. #4
    Freelancer akhileshbc's Avatar
    Join Date
    Jun 2008
    Location
    Trivandrum, Kerala, India
    Posts
    7,652

    Re: Sort multidimensional array

    You can get the upperbound of the array as follows:
    Code:
    Dim Ar(3, 8, 1, 10) As Integer
    
    MsgBox UBound(Ar, 1)    '~~~ Upperbound of 1st dimension
    MsgBox UBound(Ar, 2)    '~~~ Upperbound of 2nd dimension
    MsgBox UBound(Ar, 3)    '~~~ Upperbound of 3rd dimension
    MsgBox UBound(Ar, 4)    '~~~ Upperbound of 4th dimension
    This thread might be useful to know different sorting methods: http://www.vbforums.com/showthread.php?t=473677

    If my post was helpful to you, then express your gratitude using Rate this Post.
    And if your problem is SOLVED, then please Mark the Thread as RESOLVED (see it in action - video)
    My system: AMD FX 6100, Gigabyte Motherboard, 8 GB Crossair Vengance, Cooler Master 450W Thunder PSU, 1.4 TB HDD, 18.5" TFT(Wide), Antec V1 Cabinet

    Social Group: VBForums - Developers from India


    Skills: PHP, MySQL, jQuery, VB.Net, Photoshop, CodeIgniter, Bootstrap,...

  5. #5
    PowerPoster Code Doc's Avatar
    Join Date
    Mar 2007
    Location
    Omaha, Nebraska
    Posts
    2,354

    Re: Sort multidimensional array

    Quote Originally Posted by Khalefa...@ View Post
    Thanks I appreciate your reply
    but it seems very slow specially when using a ListBox
    the sorting process is a small part loops thousands times within a large process
    Note that above values are totally random values not fixed at all

    thanks again
    Note that I used the list box only for simplicity. Please see the Codebank for fast sorting routines. The insertion sort and my jump sort, which is a modified Shell, are my two favorites. The sorted list box is not that slow but it does use up a resource.

    When you work with multi-dimensional arrays, you are going to get involved with looping and numerous value checks. There is little you can do about that. You may wish to examine collections that seem to offer some promise in efficency. Regardless, consider that the array Ar(10, 10, 10, 10) could have 14,641 unique values without any duplicates and you could even have 14,641 combinations of the subscripts, all defining the same value.
    Last edited by Code Doc; Nov 26th, 2010 at 03:47 PM.
    Doctor Ed

  6. #6
    PowerPoster
    Join Date
    Jul 2006
    Location
    Maldon, Essex. UK
    Posts
    6,334

    Re: Sort multidimensional array

    There is an alternative. Copy the multi-dimensional array into a one-dimensional array, sort that array, then copy it back to a multi-dimensional array.
    An array like: intData(intRows, intColumns)
    Code:
    0   1   2  
    3   4   5  
    6   7   8
    is held in memory as
    Code:
    0   3   6   1   4   7   2   5   8
    ie Data for Column1, followed by Data for Column2, etc (That, by the way, is why you can only ReDim Preserve the last dimension of Dynamic Arrays)

    So to sort on a particular Column you just need to calculate which elements to start and end with in the one-dimensional array

    Here's a small example using a very nasty swap sort -I'm sure that any other sorting algorithm can be adapted for use. (I'm just to lazy to do it)

    Code:
    Option Explicit
    Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
                (Destination As Any, _
                 Source As Any, _
                 ByVal Length As Long)
    
    Private Sub Command_Click()
    Dim intData(2, 2) As Integer
    Dim intData1() As Integer
    Dim intLength As Integer
    Dim intI As Integer
    Dim intJ As Integer
    Dim intK As Integer
    Dim intCol As Integer
    Dim intTemp As Integer
    Dim intStart As Integer
    Dim boSwap As Boolean
    For intI = 0 To 2
        For intJ = 0 To 2
            intData(intI, intJ) = intK
            intK = intK + 1
        Next intJ
    Next intI
    Debug.Print "Original Array:"
    For intI = 0 To 2
        For intJ = 0 To 2
            Debug.Print intData(intI, intJ); " ";
        Next intJ
        Debug.Print
    Next intI
    
    intLength = ((UBound(intData, 1) + 1) * (UBound(intData, 2) + 1)) * 2
    ReDim intData1((intLength / 2) - 1)
    CopyMemory intData1(0), intData(0, 0), intLength
    Debug.Print
    Debug.Print "One Dimensional Array:"
    For intI = 0 To UBound(intData1)
        Debug.Print intData1(intI); " ";
    Next intI
    Debug.Print
    Debug.Print
    '
    ' Column to sort on
    ' 0 = First column, 1 = Second Column etc
    '
    intCol = 2
    intStart = intCol + ((UBound(intData, 2)) * intCol)
    '
    ' Sort into descending order
    '
    Do
        boSwap = False
        For intI = intStart To intStart + UBound(intData, 2) - 1
            If intData1(intI) < intData1(intI + 1) Then
                intTemp = intData1(intI)
                intData1(intI) = intData1(intI + 1)
                intData1(intI + 1) = intTemp
                boSwap = True
            End If
        Next intI
    Loop Until boSwap = False
    Debug.Print
    CopyMemory intData(0, 0), intData1(0), intLength
    Debug.Print "Original Array sorted on Column " & intCol + 1
    For intI = 0 To UBound(intData, 1)
        For intJ = 0 To UBound(intData, 2)
            Debug.Print intData(intI, intJ); " ";
        Next intJ
        Debug.Print
    Next intI
    End Sub
    The 'nice' things (IMHO) about this approach is that you only access the elements to be sorted (the others are ignored) and there's no nested For / Next Loops. I'm sure there's a multitude of disadvantage as well !

  7. #7
    PowerPoster Ellis Dee's Avatar
    Join Date
    Mar 2007
    Location
    New England
    Posts
    3,530

    Re: Sort multidimensional array

    Quote Originally Posted by Doogle View Post
    The 'nice' things (IMHO) about this approach is that you only access the elements to be sorted (the others are ignored) and there's no nested For / Next Loops. I'm sure there's a multitude of disadvantage as well !
    He needs to access the other elements; they need to be carried along for the ride. Note in the OP the sample data:

    Ar(0,5,1,0)=3
    Ar(1,6,1,10)=7
    Ar(2,7,1,5)=1
    Ar(3,8,1,5)=10

    After sorting

    Ar(0,8,1,5)=10
    Ar(1,6,1,10)=7
    Ar(2,5,1,0)=3
    Ar(3,7,1,5)=1

    The rows stay together during the sort. For simplicity, it's probably best to keep all the rows together and then when the sorting is finished a single linear pass could reorder the A column.

    Note that all this "row" and "column" business is how we conceptualize 2-dimensional arrays. A 3-dimensional array adds the z axis, giving you x,y and z, which is how you identify a point in a volume as opposed to a point on a plane. Adding a fourth dimension, as in this problem, adds the time element, so every point in a volume at any given interval of time.

    Just thinking about it is making my head hurt. The "row" that I said gets "carried along", for example, isn't data at all but coordinates. Coordinates can't be sorted because they are constants. In the OP, the only actual data is 3,7,1,10. The coordinates chosen seem to have no rhyme or reason behind them binding those four numbers together.

    On closer inspection, your code uses 2-dimensional arrays. That is insufficient, though I may repurpose your code for something else I'm writing at the moment so it wasn't wasted effort.
    Last edited by Ellis Dee; Nov 27th, 2010 at 11:52 AM.

  8. #8
    PowerPoster Ellis Dee's Avatar
    Join Date
    Mar 2007
    Location
    New England
    Posts
    3,530

    Re: Sort multidimensional array

    Quote Originally Posted by Khalefa...@ View Post
    I need to sort that array (descending) by the value of X
    This statement is insufficient. What dimension do you want to sort on: A, B, C or D?

    Are we sure this array has four dimensions and not two? The reason I ask is because you state that A, B, C and D can't have decimals, as if they were data. They aren't data, they're array indexes, so it goes without saying that they can't have decimals. That's why I ask.

    Also, the concept of reordering A doesn't really mesh with A being an array index, but instead it implies that A is part of the data.

  9. #9

    Thread Starter
    Lively Member
    Join Date
    Sep 2006
    Posts
    91

    Re: Sort multidimensional array

    thanks all
    finally i solve it
    the problem has been solved even if the code isn't professional

    here it is

    Code:
    Dim Ar(0 To 5, 0 To 5, 0 To 5, 0 To 5) As Integer
    Dim A As Integer, B As Integer, C As Integer, D As Integer, X As Integer
    Dim Ff As Long
    
    Private Type tSlave
        tB As Integer
        tC As Integer
        tD As Integer
        tX As Integer
    End Type
    
    Sub RandomizeAr()
        For A = 0 To 5
            For B = 0 To 5
                For C = 0 To 5
                    For D = 0 To 5
                        X = (Rnd * 1000) \ 1
                        Ar(A, B, C, D) = X
                        Print #Ff, A & "," & B & "," & C & "," & D & " = " & X
                    Next
                Next
            Next
        Next
    End Sub
    
    Private Sub Form_Load()
        Ff = FreeFile
        Open "c:\test.txt" For Output As #Ff
            Print #Ff, "Unsorted array"
            Print #Ff, "A B C D = X"
            
            RandomizeAr
            
            Print #Ff, String$(20, "#")
            Print #Ff, "##  Sorted array  ##"
            Print #Ff, String$(20, "#")
            Print #Ff, vbNullString
            Print #Ff, "A B C D = X"
            SortAr
        Close #Ff
        Shell "Notepad.exe c:\test.txt", vbNormalFocus
        End
    End Sub
    
    Sub SortAr()
        Dim Slave(0 To 1295) As tSlave
        Dim i As Integer, Sorted As Boolean, Tmp As tSlave
        
        For A = 0 To 5
            For B = 0 To 5
                For C = 0 To 5
                    For D = 0 To 5
                        With Slave(i)
                            .tB = B
                            .tC = C
                            .tD = D
                            .tX = Ar(A, B, C, D)
                        End With
                        i = i + 1
                    Next
                Next
            Next
        Next
        
        Do While Not Sorted
            Sorted = True
            For i = 0 To UBound(Slave) - 1
                If Slave(i).tX < Slave(i + 1).tX Then
                    Tmp = Slave(i + 1)
                    Slave(i + 1) = Slave(i)
                    Slave(i) = Tmp
                    Sorted = False
                End If
            Next
        Loop
        A = 0
        For i = 0 To 1295
            With Slave(i)
                Ar(A, .tB, .tC, .tD) = .tX
                Print #Ff, A & "," & .tB & "," & .tC & "," & .tD & " = " & .tX
                A = A + 1
                If A > 5 Then A = 0
            End With
        Next
        Erase Slave
    End Sub


    Ellis Dee your thread http://www.vbforums.com/showthread.php?t=473677 is very helpful

  10. #10
    PowerPoster
    Join Date
    Jul 2006
    Location
    Maldon, Essex. UK
    Posts
    6,334

    Re: Sort multidimensional array

    Quote Originally Posted by Ellis Dee View Post
    On closer inspection, your code uses 2-dimensional arrays. That is insufficient, though I may repurpose your code for something else I'm writing at the moment so it wasn't wasted effort.
    I agree, I was trying to work out whether there was a practical alternative to nested Fors etc. What I created only works for a 2D array with equal numbers of elements. It's a very special case.

    Like an idiot, I'm working on a 'general' solution' for an 'n'D array with unequal element numbers.

    Ever started something and wish you hadn't ?

  11. #11
    PowerPoster Code Doc's Avatar
    Join Date
    Mar 2007
    Location
    Omaha, Nebraska
    Posts
    2,354

    Re: Sort multidimensional array

    Quote Originally Posted by Doogle View Post
    I agree, I was trying to work out whether there was a practical alternative to nested Fors etc. What I created only works for a 2D array with equal numbers of elements. It's a very special case.

    Like an idiot, I'm working on a 'general' solution' for an 'n'D array with unequal element numbers.

    Ever started something and wish you hadn't ?
    Having worked with multi-dimensional arrays going back to the mainframe days, I could almost have guaranteed that there is no practical alternatve to "nested Fors etc." In short, if OP's problem indeed demands the use of a 4-dimensional array, all elements have to be examined at one time or another.

    I recall using canned statistical packages for multivariate analysis that could tie computers up for hours performing enormous number crunching operations in FORTRAN. I am sure that advances have been made since then, but some steps simply cannot be eliminated.

    My recommendation here would be to reconstruct the model and/or the data structure so that a 4-dimensional array is not required in the first place. I admit, however, that sometimes this is impossible. I ran into this a few years back where there was no other altrernative. Luckily, I was able to hold the number of levels of three of the dimensions to 4 or less and let the fourth be the sample size, which never exceeded 200. Thus, the looping was somewhat constrained and that saved time.
    Doctor Ed

  12. #12
    PowerPoster Ellis Dee's Avatar
    Join Date
    Mar 2007
    Location
    New England
    Posts
    3,530

    Re: [RESOLVED] Sort multidimensional array

    I believe you could construct a recursive loop to avoid the nested For...Next structure, but it's much more complex and you could easily run out of stack space. (Especially if your sorting algorithm were also recursive!) The advantage would be that it could conceivably work for any amount of dimensions.

  13. #13

    Thread Starter
    Lively Member
    Join Date
    Sep 2006
    Posts
    91

    Re: [RESOLVED] Sort multidimensional array

    Quote Originally Posted by Ellis Dee View Post
    I believe you could construct a recursive loop to avoid the nested For...Next structure, but it's much more complex and you could easily run out of stack space. (Especially if your sorting algorithm were also recursive!) The advantage would be that it could conceivably work for any amount of dimensions.
    It's true
    The nested For Next structure makes any project unstable
    but I used it just for clarifying that issue
    and I'm about to make many changes for more performance

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width