Page 1 of 1
How to redim a multi array?
Posted: Thu Oct 17, 2013 7:30 pm
by marc_256
How to redim a multi array ?
I need a multi array, and I used it in my test program with a fixed number.
After some changes in my program for User defined arrays,
I have the error message...
"Only the last dimension of an array can be changed with Redim"
Q) How can I made MyArray User definable ?
Marc,
Re: How to redim a multi array?
Posted: Thu Oct 17, 2013 8:25 pm
by skywalk
Yes, the message is correct...
Code: Select all
Define.i fixed = 10, variable = 100
Dim arrX(fixed, 0)
ReDim arrX(fixed, variable) ;<-- expand 2nd dimension to 100. Contents are preserved.
ReDim arrX(fixed, 0) ;<-- shrink 2nd dimension.
ReDim arrX(fixed+1, 0) ;<-- [ERROR] Only the last dimension of an Array can be changed With ReDim.
Re: How to redim a multi array?
Posted: Thu Oct 17, 2013 8:44 pm
by Little John
marc_256 wrote:I have the error message...
"Only the last dimension of an array can be changed with Redim"
Q) How can I made MyArray User definable ?
Yes, this is currently a limitation of PureBasic.
However, you can use an array that is technically speaking a one dimensional array, and treat it logically as a multi-dimensional array. The only drawback is, that you have to calculate the proper indexes yourself, but that's not too hard.
Here is an example for such a self-made 2-dimensional array:
Code: Select all
EnableExplicit
Macro Array2Dim (_Array_, _Dimension1_, _Dimension2_)
Dim _Array_((_Dimension1_+1)*(_Dimension2_+1))
_Array_(0) = _Dimension2_+1
EndMacro
Macro Array2ReDim (_Array_, _Dimension1_, _Dimension2_)
ReDim _Array_((_Dimension1_+1)*(_Dimension2_+1))
_Array_(0) = _Dimension2_+1
EndMacro
Macro Array2Val (_Array_, _Val1_, _Val2_)
_Array_(_Array_(0)*_Val1_ + _Val2_ + 1)
EndMacro
;=== Demo ===
Define lastIndex1.i, lastIndex2.i, count.i, i.i, k.i
;-- Set the array bounds
lastIndex1 = 2
lastIndex2 = 3
;-- Dim the array
Array2Dim(a, lastIndex1, lastIndex2)
;-- Populate the array
count = 0
For i = 0 To lastIndex1
For k = 0 To lastIndex2
count + 1
Array2Val(a, i, k) = count
Next
Next
;-- Show the array contents
For i = 0 To lastIndex1
For k = 0 To lastIndex2
Debug Array2Val(a, i, k)
Next
Next
Debug "--------"
;-- Set OTHER array bounds
lastIndex1 = 5
lastIndex2 = 4
;-- ReDim the array
Array2ReDim(a, lastIndex1, lastIndex2)
;-- Populate the array
count = 0
For i = 0 To lastIndex1
For k = 0 To lastIndex2
count + 1
Array2Val(a, i, k) = count
Next
Next
;-- Show the array contents
For i = 0 To lastIndex1
For k = 0 To lastIndex2
Debug Array2Val(a, i, k)
Next
Next
Re: How to redim a multi array?
Posted: Thu Oct 17, 2013 9:51 pm
by freak
@marc_256
You can change the size of the array by calling Dim a second time. This allows to change all dimensions, but it will not preserve the array contents:
@Little John:
Your code has the problem that resizing the array mixes up the existing values. Try the following test code:
Code: Select all
EnableExplicit
Macro Array2Dim (_Array_, _Dimension1_, _Dimension2_)
Dim _Array_((_Dimension1_+1)*(_Dimension2_+1))
_Array_(0) = _Dimension2_+1
EndMacro
Macro Array2ReDim (_Array_, _Dimension1_, _Dimension2_)
ReDim _Array_((_Dimension1_+1)*(_Dimension2_+1))
_Array_(0) = _Dimension2_+1
EndMacro
Macro Array2Val (_Array_, _Val1_, _Val2_)
_Array_(_Array_(0)*_Val1_ + _Val2_ + 1)
EndMacro
Define i, k, s$
; define and fill array
Array2Dim(a, 4, 4)
For i = 0 To 4
For k = 0 To 4
Array2Val(a, i, k) = i * 10 + k
Next k
Next i
; show it
For i = 0 To 4
s$ = ""
For k = 0 To 4
s$ + RSet(Str(Array2Val(a, i, k)), 2, "0") + " "
Next k
Debug s$
Next i
; resize first dimension and show it
Array2ReDim(a, 8, 4)
Debug "-- after resizing --"
For i = 0 To 8
s$ = ""
For k = 0 To 4
s$ + RSet(Str(Array2Val(a, i, k)), 2, "0") + " "
Next k
Debug s$
Next i
; resize second dimension and show it again
Array2ReDim(a, 8, 8)
Debug "-- after resizing --"
For i = 0 To 8
s$ = ""
For k = 0 To 8
s$ + RSet(Str(Array2Val(a, i, k)), 2, "0") + " "
Next k
Debug s$
Next i
After a ReDim of your second dimension, you'd have to move all array elements around in the array to get their right place inside the new dimensions. This is why PB allows to resize only a single dimension (the one where this is not necessary).
Re: How to redim a multi array?
Posted: Thu Oct 17, 2013 10:07 pm
by IdeasVacuum
Why not simply use a Linked List whose values are a structure?
Code: Select all
Structure MyStruct
iX.i
iY.i
EndStructure
Global NewList MyList.MyStruct()
Re: How to redim a multi array?
Posted: Fri Oct 18, 2013 6:23 am
by TI-994A
marc_256 wrote:How to redim a multi array ?
Code: Select all
Global Dim MyArray.l(10, 5)
ReDim MyArray.l(20, 5)
Hello marc_256. Here's a workaround to preserve the contents of a two-dimensional array while re-dimensioning the first. For clarity, this example works on option base 1, but can easily be adapted to work with option base 0, as well as with more dimensions:
Code: Select all
Procedure ReDim_Preserve(Array xArray.s(2), newDim1, newDim2)
Dim tempArray.s(ArraySize(xArray(), 1), ArraySize(xArray(), 2))
For L = 1 To ArraySize(xArray(), 1)
For LL = 1 To ArraySize(xArray(), 2)
tempArray(L, LL) = xArray(L, LL)
Next LL
Next L
Dim xArray(newDim1, newDim2)
For L = 1 To newDim1
For LL = 1 To newDim2
If L > ArraySize(xArray(), 1) Or LL > ArraySize(xArray(), 2) Or
L > ArraySize(tempArray(), 1) Or LL > ArraySize(tempArray(), 2)
Break
Else
xArray(L, LL) = tempArray(L, LL)
EndIf
Next LL
Next L
FreeArray(tempArray())
EndProcedure
Procedure displayArray(Array xArray.s(2), header.s)
Debug header
Debug "---"
For L = 1 To ArraySize(xArray(), 1)
For LL = 1 To ArraySize(xArray(), 2)
Debug Str(L) + "," + Str(LL) + " = " + xArray(L, LL)
Next LL
Next L
Debug ""
EndProcedure
Define L, LL, dataNames.s
Dim myArray.s(2, 4)
For L = 1 To 2
For LL = 1 To 4
Read.s dataNames
myArray(L, LL) = dataNames
Next LL
Next L
displayArray(myArray(), "orignal myArray(2, 4):")
ReDim_Preserve(myArray(), 3, 5)
displayArray(myArray(), "after ReDim_Preserve(3, 5):")
ReDim_Preserve(myArray(), 1, 3)
displayArray(myArray(), "after ReDim_Preserve(1, 3):")
DataSection
Data.s "Albert Einstein", "Isaac Newton", "Charles Darwin", "Guglielmo Marconi"
Data.s "Galileo Galilei", "Leonardo da Vinci", "René Descartes", "Thomas Edison"
EndDataSection
Not exactly sophisticated code, but it does the job.

Re: How to redim a multi array?
Posted: Fri Oct 18, 2013 7:52 am
by Lord
marc_256 wrote:How to redim a multi array ?
I need a multi array, and I used it in my test program with a fixed number.
After some changes in my program for User defined arrays,
I have the error message...
"Only the last dimension of an array can be changed with Redim"
Q) How can I made MyArray User definable ?
Marc,
What about reordering of indices?
to
so you can
Re: How to redim a multi array?
Posted: Fri Oct 18, 2013 8:37 am
by Little John
freak wrote:After a ReDim of your second dimension, you'd have to move all array elements around in the array to get their right place inside the new dimensions.
Oops.

I overlooked that. Thanks for pointing it out.
Re: How to redim a multi array?
Posted: Sat Oct 19, 2013 12:57 pm
by marc_256
thanks for helping here,
I can't lose all my data in the arrays, so I need to copy them first and then use the DIM again.
I have some time this WE, so I will look for some solutions.
And trying some stuff...
Marc,
Re: How to redim a multi array?
Posted: Sat Oct 19, 2013 3:09 pm
by IdeasVacuum
So marc, I think Linked Lists are the answer in this case - dynamic, no re-dim required, no extra code for each array required.
Re: How to redim a multi array?
Posted: Sat Oct 19, 2013 6:12 pm
by skywalk
marc_256 wrote:I can't lose all my data in the arrays, so I need to copy them first and then use the DIM again.
Now that you know the limitations of dynamic arrays, I would redesign your data structures accordingly. This is only if you require the speed advantages of arrays vs lists(which do not require contiguous memory). For large arrays, there are definite advantages over lists and maps.
Think of a 2D array like a db table. The columns are predefined. Then you add/delete rows with redim myarr(fixed #columns, ±variable rows). To change the #columns you have to remake the table with dim(new #columns, ±variable rows). Just as in SQL you need to Alter Table.
Re: How to redim a multi array?
Posted: Sun Oct 20, 2013 3:59 am
by TI-994A
marc_256 wrote:I can't lose all my data in the arrays, so I need to copy them first and then use the DIM again.
Hello again marc_256. In case you missed it, the ReDim_Preserve() routine in my example above does just that. Very basic, but it works.
