# Thread: [RESOLVED] Sort multidimensional array

1. ## [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

2. ## 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.

3. ## Re: Sort multidimensional array

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

5. ## Re: Sort multidimensional array

Originally Posted by Khalefa...@
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.

6. ## 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. ## Re: Sort multidimensional array

Originally Posted by Doogle
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.

8. ## Re: Sort multidimensional array

Originally Posted by Khalefa...@
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. ## 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

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

10. ## Re: Sort multidimensional array

Originally Posted by Ellis Dee
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. ## Re: Sort multidimensional array

Originally Posted by Doogle
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.

12. ## 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. ## Re: [RESOLVED] Sort multidimensional array

Originally Posted by Ellis Dee
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
•

Featured

Click Here to Expand Forum to Full Width

×
We have made updates to our Privacy Policy to reflect the implementation of the General Data Protection Regulation.