How to redim a multi array?

Just starting out? Need help? Post your questions and find answers here.
marc_256
Addict
Addict
Posts: 852
Joined: Thu May 06, 2010 10:16 am
Location: Belgium
Contact:

How to redim a multi array?

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

Code: Select all

Global Dim MyArray.l(10, 5)
After some changes in my program for User defined arrays,

Code: Select all

ReDim MyArray.l(20, 5)
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,
- every professional was once an amateur - greetings from Pajottenland - Belgium -
PS: sorry for my english I speak flemish ...
User avatar
skywalk
Addict
Addict
Posts: 4229
Joined: Wed Dec 23, 2009 10:14 pm
Location: Boston, MA

Re: How to redim a multi array?

Post 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.
The nice thing about standards is there are so many to choose from. ~ Andrew Tanenbaum
Little John
Addict
Addict
Posts: 4795
Joined: Thu Jun 07, 2007 3:25 pm
Location: Berlin, Germany

Re: How to redim a multi array?

Post 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
freak
PureBasic Team
PureBasic Team
Posts: 5944
Joined: Fri Apr 25, 2003 5:21 pm
Location: Germany

Re: How to redim a multi array?

Post 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:

Code: Select all

Dim x(5, 7)
;...
Dim x(42, 21)
@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).
quidquid Latine dictum sit altum videtur
IdeasVacuum
Always Here
Always Here
Posts: 6426
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: How to redim a multi array?

Post 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()
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
User avatar
TI-994A
Addict
Addict
Posts: 2741
Joined: Sat Feb 19, 2011 3:47 am
Location: Singapore
Contact:

Re: How to redim a multi array?

Post 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. :lol:
Texas Instruments TI-99/4A Home Computer: the first home computer with a 16bit processor, crammed into an 8bit architecture. Great hardware - Poor design - Wonderful BASIC engine. And it could talk too! Please visit my YouTube Channel :D
User avatar
Lord
Addict
Addict
Posts: 907
Joined: Tue May 26, 2009 2:11 pm

Re: How to redim a multi array?

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

Code: Select all

Global Dim MyArray.l(10, 5)
After some changes in my program for User defined arrays,

Code: Select all

ReDim MyArray.l(20, 5)
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?

Code: Select all

Global Dim MyArray.l(10, 5)
to

Code: Select all

Global Dim MyArray.l(5, 10)
so you can

Code: Select all

ReDim MyArray.l(5, 20)
Image
Little John
Addict
Addict
Posts: 4795
Joined: Thu Jun 07, 2007 3:25 pm
Location: Berlin, Germany

Re: How to redim a multi array?

Post 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. :oops: I overlooked that. Thanks for pointing it out.
marc_256
Addict
Addict
Posts: 852
Joined: Thu May 06, 2010 10:16 am
Location: Belgium
Contact:

Re: How to redim a multi array?

Post 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,
- every professional was once an amateur - greetings from Pajottenland - Belgium -
PS: sorry for my english I speak flemish ...
IdeasVacuum
Always Here
Always Here
Posts: 6426
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: How to redim a multi array?

Post 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.
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
User avatar
skywalk
Addict
Addict
Posts: 4229
Joined: Wed Dec 23, 2009 10:14 pm
Location: Boston, MA

Re: How to redim a multi array?

Post 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.
The nice thing about standards is there are so many to choose from. ~ Andrew Tanenbaum
User avatar
TI-994A
Addict
Addict
Posts: 2741
Joined: Sat Feb 19, 2011 3:47 am
Location: Singapore
Contact:

Re: How to redim a multi array?

Post 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. :)
Texas Instruments TI-99/4A Home Computer: the first home computer with a 16bit processor, crammed into an 8bit architecture. Great hardware - Poor design - Wonderful BASIC engine. And it could talk too! Please visit my YouTube Channel :D
Post Reply