hey guys i was wondering if someone could remind me what a 2D array is and show me a small example. We were just about to finish up on them but the the winter break came so now i have forgotten a bit. I was just wondering if someone could refresh my memory, thanks to anyone who helps out.
You can think of a 2 D array as a Matrix, with Rows and Columns
eg
Code:
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
To define the array:eg.
Code:
Dim intArray(Number of Rows - 1, Number of Columns - 1) As Integer
'
' So for the example above - 3 rows, 5 columns
'
Dim intArray(2,4) As Integer
(Assumes you're not using Option Base 1)
To allocate values
Code:
intArray(0,0) = 1 'Row 1, Col 1
intArray(0,1) = 2 'Row 1, Col 2
intArray(0,2) = 3 'Row 1, Col 3
intArray(0,3) = 4 'Row 1, Col 4
intArray(0,4) = 5 'Row 1, Col 5
intArray(1,0) = 6 'Row 2, Col 1
intArray(1,1) = 7 'Row 2, Col 2
'etc up to
intArray(2,4) = 15 'Row 3, Col 5
You can do all sorts of interesting things with them
eg
Adding up the Rows:
Code:
Dim intRow As Integer
Dim intCol As Integer
Dim intRowTotal as Integer
For intRow = 0 to 2
intRowTotal = 0
For intCol = 0 To 4
intRowTotal = intRowTotal + intArray(intRow, intCol)
Next intCol
Debug.print "Row ";intRow;" Total = "; intRowTotal
Next intRow
Whether you think of the matrix as Rows and Columns or as Columns and Rows is up to you (or, perhaps your instructor )
ie you could define the array as
Code:
Dim intArray(Number of Columns - 1, Number of Rows - 1)
but of course you'd have to populate and process it accordingly. In fact, VB stores Arrays in memory in Cols and Rows - I prefer to think of them as Rows and Columns as it's more intuitive (that's the way i read)
To piggy back on Doogle's response....
You can also think of a 2D array as Columns and Rows vs Rows & Columns. VB allows you to resize an array while keeping the existing array data, but only the last dimension of the array can be resized. Therefore, if this is a possibility in your code -- resizing array, then place the dimension that could be resized at the end....
Code:
'think of 2D arrays as grids/spreadhseets.
' Here I am expecting number of rows to grow/shrink. So I want the
' last dimension to reference the grid rows vs columns
Dim aGrid() As Long
ReDim aGrid(0 to 99, 0 to 4) As Long
' grid is now 100 columns (0-99), by 5 rows (0 to 4)
ReDim Preserve aGrid(0 to 99, 0 to 19)
' grid grew to 20 rows (0 to 19)
You can also use 1-dimensional array as 2-dimensional:
Code:
Dim Table() As Long, lngX As Long, lngY As Long, lngIndex As Long
' assuming a table of 100 x 50 = 5000 items
ReDim Table(4999)
' X and Y position from index
lngX = lngIndex Mod 100
lngY = lngIndex \ 100
' index from X and Y position
lngIndex = lngX + lngY * 100
Zero based one dimensional arrays are the fastest arrays to access in VB6 due to the compiler's inability to optimize arrays of other bases, so using the lightweight \ and Mod math operators with 1D array is often quicker than using a real 2D array.
You can also resize the array just as you like, although you need to reposition stuff manually. But atleast doing that is easier than doing it with 2D arrays (afaics).
Merri, your statement about speed got me curious. Here is confirmation of what you said, along with another speed enhancement not many may be aware of.
Using a similar approach to yours (without mod & integer division).
Code:
Private Sub Command1_Click()
Dim a() As Long, t As Double
Dim r As Long, c As Long, Index As Long, z As Long
Const nrRows As Long = 7000
Const nrCols As Long = 7000
Const someValue As Long = 371962
ReDim a(0 To nrCols - 1, 0 To nrRows - 1)
t = Timer
For r = 0 To nrRows - 1
For c = 0 To nrCols - 1
z = a(c, r) ' reading from the array
'a(c, r) = someValue ' writing to the array
Next
Next
Debug.Print Timer - t,
ReDim a(0 To nrRows * nrCols - 1)
t = Timer
For r = 0 To nrRows - 1
Index = r * nrCols
For c = 0 To nrCols - 1
z = a(Index + c) ' reading from the array
'a(Index + c) = someValue ' writing to the array
Next
Next
Debug.Print Timer - t
' the results (in seconds) on my pc, each run 3x and picked best times:
' Reading: 5.4234 for 1st loop, 2.79612 for 2nd loop
' Writing: 5.3144 for 1st loop, 3.3164 for 2nd loop
End Sub
Now many of us have learned to reference 2D arrays as rows and columns and we dim our arrays like that Array(rows,cols).
However, this is really inefficient vs the other way around: Array(cols,rows).
Why? Simply, that is how it is stored in memory and accessing it that way is faster overall:
Code:
Private Sub Command2_Click()
Dim a() As Long, t As Double
Dim r As Long, c As Long, z As Long
Const nrRows As Long = 7000
Const nrCols As Long = 7000
' organizing 2D array by cols then rows is faster
' than the other way around when you expect to access by cols.
' 2D is columns then rows
ReDim a(0 To nrCols - 1, 0 To nrRows - 1)
t = Timer
For r = 0 To nrRows - 1
For c = 0 To nrCols - 1
z = a(c, r)
Next
Next
Debug.Print Timer - t,
' 2D is rows then columns
ReDim a(0 To nrRows - 1, 0 To nrCols - 1)
t = Timer
For r = 0 To nrRows - 1
For c = 0 To nrCols - 1
z = a(r, c)
Next
Next
Debug.Print Timer - t
' the results (in seconds) on my pc, each run 3x and picked best times:
' 5.4985 for col,row order, 8.8676 for row,col order
End Sub
Note: Simple timing only, can vary when compiled. But it does seem to prove the points made.
That's a revelation to me....
I made some pretty pictures to better show the difference.
I always get confused when talking column/row so I've called it Sequential non-Sequential
The code I tested is basically this...
Code:
Option Explicit
Const ITERATIONS As Long = 1000
Public Const StrTitle As String = "Dim A(" & ITERATIONS & ", " & ITERATIONS & ")"
Public Const StrTest1 As String = "2D Non-Sequential Access: Reading"
Public Const StrTest2 As String = "2D Sequential Access: Reading"
Private A() As Long
Private V As Long
Public Sub setup()
Dim i As Long, j As Long
ReDim A(ITERATIONS, ITERATIONS)
For i = 0 To ITERATIONS
For j = 0 To ITERATIONS
A(j, i) = i + j
Next
Next
End Sub
Sub TestCode1()
Dim i As Long, j As Long
'V = Rnd * &Hffffff
For i = 0 To ITERATIONS
For j = 0 To ITERATIONS
V = A(i, j)
'A(i, j) = V
Next
Next
End Sub
Sub TestCode2()
Dim i As Long, j As Long
'V = Rnd * &Hffffff
For i = 0 To ITERATIONS
For j = 0 To ITERATIONS
V = A(j, i)
'A(j, i) = V
Next
Next
End Sub
Milk, nice visualization. Sequential is easily faster. This is the main reason why I re-learned how I create arrays, who says you can't teach an old dog new tricks. I do admit I will get a bit lazy and use a 2D array vs using a 1D array and faking 2D (as show in the 1st part of my example). But I always (or try at least) to organize arrays in column, row order, from left to right.
By the way, it works on any size array and speed can be dramatic on large arrays. If one were to take a 3D array, organizing it as: (columns, rows, page) is far faster than (page, rows, column).