-
Nov 25th, 2010, 07:26 PM
#1
Thread Starter
Lively Member
[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.
-
Nov 25th, 2010, 11:02 PM
#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.
Last edited by Code Doc; Nov 26th, 2010 at 12:08 AM.
Doctor Ed
-
Nov 26th, 2010, 03:14 AM
#3
Thread Starter
Lively Member
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
-
Nov 26th, 2010, 03:35 AM
#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
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,...
-
Nov 26th, 2010, 03:26 PM
#5
Re: Sort multidimensional array
Originally Posted by Khalefa...@
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
-
Nov 27th, 2010, 03:53 AM
#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)
is held in memory as
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 !
-
Nov 27th, 2010, 11:47 AM
#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.
Last edited by Ellis Dee; Nov 27th, 2010 at 11:52 AM.
-
Nov 27th, 2010, 12:00 PM
#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.
-
Nov 27th, 2010, 07:57 PM
#9
Thread Starter
Lively Member
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
-
Nov 28th, 2010, 01:00 AM
#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 ?
-
Nov 28th, 2010, 10:35 PM
#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.
-
Nov 29th, 2010, 02:13 PM
#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.
-
Nov 30th, 2010, 11:51 AM
#13
Thread Starter
Lively Member
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
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|