Home > Archive > Visual Basic Syntax > August 2005 > redim preserve multidimen array
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
| Author |
redim preserve multidimen array
|
|
| Martin 2005-07-28, 4:03 am |
| Hi,
I am trying use create a dynamic multidimen. array with DIM and REDIM
PRESERVE, but it doesn't work. Can anybody help me?
Dim l_vAray() As Variant
dim c as integer
For r = 1 To 3
Redim Preserve l_vAray(r, 5)
For c = 0 To 4
l_vAray(r - 1, c) = "yyy
Next c
Next r
the line ReDim Preserve l_vAray(r, 5) works only once, where r = 1
Why?
Thanks
Martin
| |
| Rick Rothstein [MVP - Visual Basic] 2005-07-28, 4:03 am |
| > I am trying use create a dynamic multidimen. array with DIM and REDIM
> PRESERVE, but it doesn't work. Can anybody help me?
>
> Dim l_vAray() As Variant
> dim c as integer
> For r = 1 To 3
> Redim Preserve l_vAray(r, 5)
> For c = 0 To 4
> l_vAray(r - 1, c) = "yyy
> Next c
> Next r
>
> the line ReDim Preserve l_vAray(r, 5) works only once, where r = 1
> Why?
You can only ReDim the **last** dimension of an array when using the
Preserve option. So, you will have to think in reverse for what you
posted above...
Dim l_vArray() As Variant
Dim c As Integer
For r = 1 To 3
ReDim Preserve l_vArray(5, r)
For c = 0 To 4
l_vArray(c, r - 1) = "yyy"
Next
Next
where I presume the r variable was Dim'med outside of the procedure the
above code is in.
Rick
| |
| Martin 2005-07-28, 4:03 am |
| OK, thanks
Martin
"Rick Rothstein [MVP - Visual Basic]" <rickNOSPAMnews@NOSPAMcomcast.net>
schrieb im Newsbeitrag news:#6aYTy0kFHA.1048@tk2msftngp13.phx.gbl...
>
> You can only ReDim the **last** dimension of an array when using the
> Preserve option. So, you will have to think in reverse for what you
> posted above...
>
> Dim l_vArray() As Variant
> Dim c As Integer
> For r = 1 To 3
> ReDim Preserve l_vArray(5, r)
> For c = 0 To 4
> l_vArray(c, r - 1) = "yyy"
> Next
> Next
>
> where I presume the r variable was Dim'med outside of the procedure the
> above code is in.
>
> Rick
>
>
| |
| Duane Bozarth 2005-07-28, 5:04 pm |
| Martin wrote:
>
> OK, thanks
> Martin
The reason is that VB use column-major storage order so in order to
ReDim other than the last dimension would entail a copy operation so it
isn't implemented for performance reasons.
Also, while in your code the size of the loop is so small as to be
insignificant, it would be better to try to rearrange the code to remove
the ReDim from within the For...Next loop--in larger apps it could be a
real performance bottleneck. If it is mandatory, the preferred
technique is to make an initial allocation of reasonable size, iterate
until that allocation is full, then make another sizable reallocation.
Once done, if necessary the final array can be ReDim'ed to it's final
used size...
Also, from a performance standpoint working through an array in
linear-memory-access sequence will help performance significantly for
arrays of significant size. In your case
For c = 0 To 4
l_vAray(r - 1, c) = "yyy"
Next c
rearranging the array to l_vAray(c, r - 1) would allow both to be
achieved.
One last efficiency is to use Long integers for array and loop indices
is also slightly more efficient ...
HTH...
[color=darkred]
> "Rick Rothstein [MVP - Visual Basic]" <rickNOSPAMnews@NOSPAMcomcast.net>
> schrieb im Newsbeitrag news:#6aYTy0kFHA.1048@tk2msftngp13.phx.gbl...
| |
| Russ Holsclaw 2005-08-02, 5:04 pm |
| "Duane Bozarth" <dpbozarth@swko.dot.net> wrote in message
news:42E8EFE1.75BD74DE@swko.dot.net...
> The reason is that VB use column-major storage order so in order to
> ReDim other than the last dimension would entail a copy operation so it
> isn't implemented for performance reasons.
>...snip the rest...
Some years back, I was faced with the task of implementing a matrix ... a
two-dimension array ... in which *both* dimensions had to be expandable.
This had to be retrofitted into code that was originally designed to work
with a matrix whose size was determined at initialization time. In fact,
the original program had been implemented in VB 3.0 without the benefit of
objects. Fortunately, VB 4.0, with the introduction of user-written
classes, came to the rescue.
My solution was to constuct an "object" that represented the array,
encapsulating a structure that was, in fact, an array of arrays. One
advantage of this was that I could write the object so that the matrix
would automatically "stretch" itself to accomodate whatever data was
assigned to it.
Here are the property Get and Let procs for the "Value" property, the
property that encapsulates the apparant behavior of a two-dimensional array
of indeterminate size.
Because the Value property had a syntax identical to that of code that's
addressing a two-dimensional array, the code that referenced it was very
little changed, except for the addition of ".Value" between the array name
and the "subscripts". This could be accomplished with a simple
Search-and-replace.
I had other methods that were peculiar to this beast, such as methods to
delete
entire rows and columns, but these procs are the "heart and soul" of the
thing:
'----------------------------------------------
'...at class-module level:
Private VecAray() As Variant
Private Numrows As Long 'v2.2
Private NumCols As Long 'v2.2
'----------------------------------Get proc--------------
Public Property Get _
Value(ByVal R As Long, ByVal C As Integer) As Integer
' The Value property of the object is seen to the
' caller as a two-dimensional array, whose uninitialized
' elements are initialized to -2 (the default for this app.)
' R is the row number
' C is the column
If R <= Numrows Then
If UBound(VecAray(R)) >= C Then
Value = VecAray(R)(C)
Else
Value = -2 'return undefined value
End If
Else
Value = -2 'return undefined value for this
End If
End Property
'-------------------------Let procedure-----------------------
Public Property Let _
Value(ByVal R As Long, _
ByVal C As Integer, _
ByVal vNewValue As Integer) 'v2.2
' The Value property of the object is seen to the
' caller as a two-dimensional array, whose uninitialized
' elements are initialized to -2 (the "default" value)
' R is the row number
' C is the column
Dim I As Long
Dim J As Long
Dim v As Variant 'temporary variable to hold an integer array
'VecAray is a variant array of arrays)
If C > NumCols Then NumCols = C
If R > UBound(VecAray) Then
'if too low, stretch the array, adding 1024 elements at a time
ReDim Preserve VecAray(R + 1024&) As Variant
End If
'make an array for all rows up to this one
If R > Numrows Then 'if rows beyond what's initialized
For I = Numrows + 1 To R
'set arrays into each one
ReDim Tempary(NumCols) As Integer
For J = 0 To NumCols
Tempary(J) = -2 'set to undefined value
Next J
VecAray(I) = Tempary() 'set array into variant
Next I
Numrows = R
End If
'check to see if horiz. array stretching is needed
If C > UBound(VecAray(R)) Then
v = VecAray(R)
K = UBound(v) 'old upper bound
ReDim Preserve v(NumCols) As Integer 'enlarge array
For I = K + 1 To NumCols
v(I) = -2 'initialize new elements
Next I
VecAray(R) = v 'replace existing row array in object
End If
' Here's where the real work is done, after any
' needed array-stretching...
VecAray(R)(C) = vNewValue 'set the element's value
End Property
---
Russ Holsclaw
| |
| Larry Serflaten 2005-08-02, 10:03 pm |
|
"Russ Holsclaw" <russ@holsclaw.nyet> wrote
>
> Some years back, I was faced with the task of implementing a matrix ... a
> two-dimension array ... in which *both* dimensions had to be expandable.
> This had to be retrofitted into code that was originally designed to work
> with a matrix whose size was determined at initialization time.
<...>
> My solution was to constuct an "object" that represented the array,
> encapsulating a structure that was, in fact, an array of arrays. One
> advantage of this was that I could write the object so that the matrix
> would automatically "stretch" itself to accomodate whatever data was
> assigned to it.
<...>
> Because the Value property had a syntax identical to that of code that's
> addressing a two-dimensional array, the code that referenced it was very
> little changed, except for the addition of ".Value" between the array name
> and the "subscripts". This could be accomplished with a simple
> Search-and-replace.
You could have avoided the search and replace by assigning the Value
property as the default property of the class (Tools > Procedure Attributes > Advanced)
I tried your code but it would not work as written, here is a class for
copy and paste code into a new class module....
(Remember to set the default property to Matrix to allow for
clsArray(X, Y) = Number type of access!)
LFS
Option Explicit
Private Data() As Variant
Private SizeX As Long, SizeY As Long
Const DEFAULT_VALUE = -2
Const INCREMENT_AMOUNT = 2
Public Property Get Matrix(ByVal x As Long, ByVal y As Long) As Integer
' Set Matrix as default property
Matrix = DEFAULT_VALUE
If (x <= SizeX) And (y <= SizeY) Then
Matrix = Data(x)(y)
End If
End Property
Public Property Let Matrix(ByVal X As Long, ByVal Y As Long, ByVal Value As Integer)
' Increase size as needed
If x > SizeX Then NewSizeX x
If y > SizeY Then NewSizeY y
Data(x)(y) = Value
End Property
Public Sub ReDimension(ByVal SizeX As Long, ByVal SizeY As Long)
If (SizeX > 0) And (SizeY > 0) Then
NewSizeY SizeY
NewSizeX SizeX
End If
End Sub
Private Sub NewSizeX(ByVal Size As Long)
' Increase columns
Dim idx As Long, init As Long
Dim tmp As Variant
If Size > SizeX Then
' Up-size all items in the array
For idx = LBound(Data) To UBound(Data)
tmp = Data(idx)
ReDim Preserve tmp(Size + INCREMENT_AMOUNT)
For init = SizeX + 1 To UBound(tmp)
tmp(init) = DEFAULT_VALUE
Next
Data(idx) = tmp
Next
SizeX = UBound(tmp)
ElseIf Size < SizeX Then
' Down-size all items in the array
For idx = LBound(Data) To UBound(Data)
tmp = Data(idx)
ReDim Preserve tmp(Size)
Data(idx) = tmp
Next
SizeX = UBound(tmp)
End If
End Sub
Private Sub NewSizeY(ByVal Size As Long)
' Increase rows
Dim idx As Long, init As Long
Dim tmp As Variant
If Size > SizeY Then
' Up-size array
ReDim Preserve Data(LBound(Data) To Size + INCREMENT_AMOUNT)
' init new items
For idx = SizeY + 1 To UBound(Data)
ReDim tmp(SizeX)
For init = LBound(tmp) To UBound(tmp)
tmp(init) = DEFAULT_VALUE
Next
Data(idx) = tmp
Next
SizeY = UBound(Data)
ElseIf Size < SizeY Then
' Down-size array
If Size >= LBound(Data) Then
ReDim Preserve Data(LBound(Data) To Size)
End If
End If
End Sub
Friend Sub DeBug_Sizes()
Dim y
For y = LBound(Data) To UBound(Data)
Debug.Print "Row "; y, LBound(Data(y)); " to "; UBound(Data(y))
Next
End Sub
Friend Sub DeBug_Values()
Dim X, Y, Z
For y = LBound(Data) To UBound(Data)
z = Data(y)
For x = LBound(z) To UBound(z)
Debug.Print z(x); ", ";
Next
Debug.Print
Next
End Sub
Private Sub Class_Initialize()
' Init data so LBound/UBound will not error on first use
Dim tmp As Variant
ReDim tmp(0)
tmp(0) = DEFAULT_VALUE
ReDim Data(0)
Data(0) = tmp
End Sub
Private Sub Class_Terminate()
Erase Data
End Sub
| |
|
| "Larry Serflaten" <serflaten@usinternet.com> wrote ...
> You could have avoided the search and replace by assigning the Value
> property as the default property of the class (Tools > Procedure
Attributes > Advanced)
I don't recall whether that was an option in VB 4.0. In any case, it wasn't
exactly obvious how to do that, and it was just about my first object in VB.
Anyway, by the time I learned about "default properties", I had already
fixed it in my code. It took only a few seconds.
On the whole, I have mixed feelings about the concept of default properties.
I gather that they dropped the idea altogether in .net. It sort of gets in
the way of having a class assignment operator overload.
> I tried your code but it would not work as written, here is a class for
> copy and paste code into a new class module....
I didn't include the whole class, just the key part ... I changed a couple
of variable names to make it appear more generalized... I may have messed it
up, I was in a rush.
In any case, the original works, and has been doing so flawlessly for about
8 years.
> (Remember to set the default property to Matrix to allow for
> clsArray(X, Y) = Number type of access!)
| |
| Ken Halter 2005-08-03, 5:06 pm |
| "Russ" <russ@holsclaw.nyet> wrote in message
news:uJoTHF$lFHA.3656@TK2MSFTNGP09.phx.gbl...
> "Larry Serflaten" <serflaten@usinternet.com> wrote ...
>
> Attributes > Advanced)
>
>
> On the whole, I have mixed feelings about the concept of default
> properties.
> I gather that they dropped the idea altogether in .net. It sort of gets
> in
> the way of having a class assignment operator overload.
>
Default properties cause far more grief/confusion than they prevent imo.
--
Ken Halter - MS-MVP-VB - http://www.vbsight.com
DLL Hell problems? Try ComGuard - http://www.vbsight.com/ComGuard.htm
Please keep all discussions in the groups..
| |
| Bob Butler 2005-08-03, 5:06 pm |
| "Ken Halter" <Ken_Halter@Use_Sparingly_Hotmail.com> wrote in message
news:%230KE9pDmFHA.3656@TK2MSFTNGP09.phx.gbl
> "Russ" <russ@holsclaw.nyet> wrote in message
> news:uJoTHF$lFHA.3656@TK2MSFTNGP09.phx.gbl...
>
> Default properties cause far more grief/confusion than they prevent
> imo.
Definitely. With the possible exception of the .Item default for
collection-type objects they should be avoided. They only make code less
clear and harder to maintain.
--
Reply to the group so all can participate
VB.Net: "Fool me once..."
| |
| Larry Serflaten 2005-08-03, 10:02 pm |
|
"Bob Butler" <tiredofit@nospam.com> wrote
>
> Definitely. With the possible exception of the .Item default for
> collection-type objects they should be avoided. They only make code less
> clear and harder to maintain.
What major difference is there between defaulting the Item property of
a collection, and the Value property of an array? If the class is desired
to act like an array (in this case a 2 dimensional array), then allowing it to
be called like one is the natural thing to do....
LFS
|
|
|
|
|