20

I am trying to move data from 2 Double Arrays to 2 different Double Arrays. I'm not sure what the size is going to be because I am taking a randomized sample out of the first arrays and putting it into the 2nd arrays.

When I add the ReDim Preserve line I get the Subscript Out of Range error.

Function CreateTrainingSet(TrainingPercent As Double, Inputs() As Double, Outputs() As Double)
 ' Create Randomized Training set data
 Dim TrainingInputs() As Double, TrainingOutputs() As Double
 Dim i As Integer, j As Integer, count As Integer
 'ReDim TrainingInputs(UBound(Inputs, 1), UBound(Inputs, 2))
 'ReDim TrainingOutputs(UBound(Outputs, 1), UBound(Outputs, 2))
 count = 0

 ' Move TraningPercent % of data from Inputs and Outputs to TrainingInputs and TrainingOutputs
 For i = LBound(Inputs, 1) To UBound(Inputs, 1)
  Dim ran As Double
  ran = Rnd()
  If ran <= TrainingPercent Then
   count = count + 1
   For j = LBound(Inputs, 2) To UBound(Inputs, 2)
    ReDim Preserve TrainingInputs(1 To count, 1 To UBound(Inputs, 2))
    TrainingInputs(count, j) = Inputs(i, j)
   Next j
   For j = LBound(Outputs, 2) To UBound(Outputs, 2)
    ReDim Preserve TrainingOutputs(1 To count, 1 To UBound(Outputs, 2))
    TrainingOutputs(count, j) = Outputs(i, j)
   Next j
  End If
 Next i

 For i = LBound(TrainingInputs, 1) To UBound(TrainingInputs, 1)
  For j = LBound(TrainingInputs, 2) To UBound(TrainingInputs, 2)
   Cells(i, j + 10).Value = TrainingInputs(i, j)
  Next j
 Next i


End Function
Carl Onager
  • 4,112
  • 2
  • 38
  • 66
atomant
  • 339
  • 1
  • 2
  • 9
  • Do you get the error on the `redim preserve` line? – PowerUser Apr 30 '14 at 16:17
  • 17
    You can only redim the *last* dimension of a 2-D array when using `Preserve`. – Tim Williams Apr 30 '14 at 16:19
  • Thanks Tim. Is there another way to do this then? – atomant Apr 30 '14 at 16:29
  • 2
    Tim's correct. You'll have to Redim a new array, without Preserve, and repopulate it every time. The good news is that there was wasn't much of performance gain on preserving the array - the memory allocation is the slowest thing you do, so much so that looping through the new array to populate it makes almost no difference. – Nigel Heffernan Apr 30 '14 at 17:27
  • 1
    an alternative i normally use is to use a collection to store each of my result rows (add a 1-d array to the collection representing each row) rather than redimensioning an array each time. At the very end I then make a single array from collection that I then assign to the output worksheet. Alternatively you can use a jagged array - that is a 1-d array you redim preserve each time with the elements in the array holding another array. – Cor_Blimey Apr 30 '14 at 18:14
  • 1
    You're not resizing the second dimension, so just flip your array dimensions around. `ReDim Preserve TrainingInputs(1 To UBound(Inputs, 2), 1 To count)` – Tim Williams Apr 30 '14 at 23:44

1 Answers1

41

To summarise the comments above into an answer:

  • You can only redim the last dimension of a multi dimension array when using Preserve.

Therefore in order to resize a multiple dimension array there are a couple of simple options:

  1. If only one dimension needs to be resized flip the loops and logic around so that the dimension to be resized becomes the last dimension
  2. If both dimensions must be resized use either an array of arrays or a collection of arrays and correct the loops as required
BigBen
  • 46,229
  • 7
  • 24
  • 40
Carl Onager
  • 4,112
  • 2
  • 38
  • 66
  • So how can we handle a function such as ActiveSheet.Shapes.AddCurve() which require a multidimentional array of (n, 2), where each n represent an X and Y coordinate. How can I size that array if the number of items is calculated at runtime ? – FMaz008 Feb 21 '23 at 17:13