For those who tend to create their own Arrays it's inevitable that sometimes ReDim will have to be used. Sometimes knowing the final size of the Array isn't known, especially if using FileFindFirstFile/FileFindNextFile to record the file name(s). For most we use ReDim $aArray[$iTotal_Rows + 1] to increase the size of the Array (by 1 Row) but when it comes to Arrays that might have 1000+ items this starts to slow the Script down. So a little trick Melba23/KaFu pointed out, is to only ReDim when really necessary & then if so multiply the size by 1.5 and round to the next integer. Thus reducing the need for 'ReDimming' every time.
For Example if we were to create an Array with 1000 items using the traditional way, it would require the Array to be ReDimmed (you guessed it) 1000 times, but using the trick (when required and multiply by 1.5) this is reduced to only 16 times! In the tests I conducted this was the difference of 388ms VS 20ms, what a huge speed increase and only on 1000 items.
The reason why I haven't made this a UDF is because users declare variables differently. How I do it is I store the row size in index 0 and if using columns I store the size in index 0 & column 1. Others will use Ubound to find the size as they don't store the Array size in the Array or in a variable e.g. For $i = 0 To Ubound($aArray, 1) - 1. Others will store the row size in index 0, but won't keep a reference of how many columns the Array has, especially when they just 'hard code' it in Functions e.g. $aArray[$i][5] += 1.
Note: As I've understood it the larger the Array becomes the slower Ubound() will become too, this is why I tend not to use Ubound(), but for those that do I have included an Example as well.
How I declare Arrays:
#include <Array.au3> Local $a1D[6] = [5, 1, 2, 3, 4, 5] ; Array count in the 0th element e.g. 5. Local $a2D[6][3] = [[5, 3], [1, 1], [2, 2], [3, 3], [4, 4], [5, 5]] ; Array count in the 0th element, 0th column e.g. 5 and the column count in the 0th element, 1st column e.g. 3. _ArrayDisplay($a1D, '1D Array') _ArrayDisplay($a2D, '2D Array')
Therefore have a look at the Examples that are below and read the comments to understand a little further. Comments, suggestions, then please post below. Thanks.
Functions.
Func _ReDim1D(ByRef $aArray, ByRef $iDimension) ; Where Index [0] is the Row count. If ($aArray[0] + 1) >= $iDimension Then $iDimension = Ceiling(($aArray[0] + 1) * 1.5) ReDim $aArray[$iDimension] Return 1 EndIf EndFunc ;==>_ReDim1D Func _ReDim2D(ByRef $aArray, ByRef $iDimension) ; Where Index [0, 0] is the Row count and Row [0, 1] is the Column count. If ($aArray[0][0] + 1) >= $iDimension Then $iDimension = Ceiling(($aArray[0][0] + 1) * 1.5) ReDim $aArray[$iDimension][$aArray[0][1]] Return 1 EndIf EndFunc ;==>_ReDim2D Func _ReDim1D_Ubound(ByRef $aArray, ByRef $iDimension, ByRef $iCount) ; Using Ubound($aArray, 1) to find the Row size. $iCount += 1 If ($iCount + 1) >= $iDimension Then $iDimension = Ceiling((UBound($aArray, 1) + 1) * 1.5) ReDim $aArray[$iDimension] Return 1 EndIf EndFunc ;==>_ReDim1D_Ubound Func _ReDim2D_Ubound(ByRef $aArray, ByRef $iDimension, ByRef $iCount) ; Using Ubound($aArray, 1) to find the Row size and Ubound($aArray, 2) for the Column size. $iCount += 1 If ($iCount + 1) >= $iDimension Then $iDimension = Ceiling((UBound($aArray, 1) + 1) * 1.5) ReDim $aArray[$iDimension][UBound($aArray, 2)] Return 1 EndIf EndFunc ;==>_ReDim2D_Ubound
Example use of Functions:
#include <Array.au3> _1D_Slow() ; See how Slow this is by doing it the traditional way of increasing by 1. _1D_1() ; Only ReDim when required and if so mutliply the count by 1.5 and round to the next integer. _1D_2() ; Only ReDim when required and if so mutliply the count by 1.5 and round to the next integer. _2D_1() ; Only ReDim when required and if so mutliply the count by 1.5 and round to the next integer, this also uses Ubound() to find the size of the Array. _2D_2() ; Only ReDim when required and if so mutliply the count by 1.5 and round to the next integer, this also uses Ubound() to find the size of the Array. Func _1D_Slow() Local $aArray[1] = [0], $hTimer = 0, $iArray = 5000, $iCount = 0, $iDimension = 0 $hTimer = TimerInit() ; Start the timer. For $i = 1 To $iArray ReDim $aArray[($aArray[0] + 1) + 1] ; ReDim the Array by adding 1 to the total count and then increasing by 1 for a new row. $iCount += 1 ; If Array was ReDimmed then add to the ReDim count for output at the end. $aArray[0] += 1 ; Increase Index [0] by 1. $aArray[$i] = 'Row ' & $i & ': Col 0' ; Add random data. If Mod($i, 1000) = 0 Then ConsoleWrite('It''s still working! Now we''re at about ' & $i & ' elements in the array.' & @CRLF) EndIf Next $hTimer = Round(TimerDiff($hTimer)) ; End the timer and find the difference from start to finish. ReDim $aArray[$aArray[0] + 1] ; Remove the empty Rows, by ReDimming the total count plus the row for holding the count. _ArrayDisplay($aArray) MsgBox(4096, 'How many times?', 'The amount of times a ' & $iArray & ' element array was ''ReDimmed'' was ' & $iCount & ' times.' & @CRLF & _ 'It only took ' & $hTimer & ' milliseconds to complete.') EndFunc ;==>_1D_Slow Func _1D_1() Local $aArray[1] = [0], $hTimer = 0, $iArray = 5000, $iCount = 0, $iDimension = 0 $hTimer = TimerInit() ; Start the timer. For $i = 1 To $iArray If _ReDim1D($aArray, $iDimension) Then ; Returns 1 if ReDimmed OR 0 if it wasn't. This uses ByRef, so just pass the Array and a previously delcared variable for monbitoring the dimension. $iCount += 1 ; If Array was ReDimmed then add to the ReDim count for output at the end. EndIf $aArray[0] += 1 ; Increase Index [0] by 1. $aArray[$i] = 'Row ' & $i & ': Col 0' ; Add random data. Next $hTimer = Round(TimerDiff($hTimer)) ; End the timer and find the difference from start to finish. ReDim $aArray[$aArray[0] + 1] ; Remove the empty Rows, by ReDimming the total count plus the row for holding the count. ; _ArrayDisplay($aArray) MsgBox(4096, 'How many times?', 'The amount of times a ' & $iArray & ' element array was ''ReDimmed'' was ' & $iCount & ' times.' & @CRLF & _ 'It only took ' & $hTimer & ' milliseconds to complete.') EndFunc ;==>_1D_1 Func _1D_2() Local $aArray[1] = [0], $hTimer = 0, $iArray = 5000, $iCount = 0, $iDimension, $iIndexTotal = 0 $hTimer = TimerInit() ; Start the timer. For $i = 1 To $iArray If _ReDim1D_Ubound($aArray, $iDimension, $iIndexTotal) Then ; Returns 1 if ReDimmed OR 0 if it wasn't. This uses ByRef, so just pass the Array and a previously delcared variable for monbitoring the dimension and a second variable for monitoring the total count. $iCount += 1 ; If Array was ReDimmed then add to the ReDim count for output at the end. EndIf $aArray[0] += 1 ; Increase Index [0] by 1. $aArray[$i] = 'Row ' & $i & ': Col 0' ; Add random data. Next $hTimer = Round(TimerDiff($hTimer)) ; End the timer and find the difference from start to finish. ReDim $aArray[$aArray[0] + 1] ; Remove the empty Rows, by ReDimming the total count plus the row for holding the count. ; _ArrayDisplay($aArray) MsgBox(4096, 'How many times?', 'The amount of times a ' & $iArray & ' element array was ''ReDimmed'' was ' & $iCount & ' times.' & @CRLF & _ 'It only took ' & $hTimer & ' milliseconds to complete.') EndFunc ;==>_1D_2 Func _2D_1() Local $aArray[1][2] = [[0, 2]], $hTimer = 0, $iArray = 5000, $iCount = 0, $iDimension = 0 $hTimer = TimerInit() ; Start the timer. For $i = 1 To $iArray If _ReDim2D($aArray, $iDimension) Then ; Returns 1 if ReDimmed OR 0 if it wasn't. This uses ByRef, so just pass the Array and a previously delcared variable for monbitoring the dimension. $iCount += 1 ; If Array was ReDimmed then add to the ReDim count for output at the end. EndIf $aArray[0][0] += 1 ; Increase Index [0, 0] by 1. $aArray[$i][0] = 'Row ' & $i & ': Col 0' ; Add random data. $aArray[$i][1] = 'Row ' & $i & ': Col 1' ; Add random data. Next $hTimer = Round(TimerDiff($hTimer)) ; End the timer and find the difference from start to finish. ReDim $aArray[$aArray[0][0] + 1][$aArray[0][1]] ; Remove the empty Rows, by ReDimming the total count plus the row for holding the count and include the number of colums too. ; _ArrayDisplay($aArray) MsgBox(4096, 'How many times?', 'The amount of times a ' & $iArray & ' element array was ''ReDimmed'' was ' & $iCount & ' times.' & @CRLF & _ 'It only took ' & $hTimer & ' milliseconds to complete.') EndFunc ;==>_2D_1 Func _2D_2() Local $aArray[1][2] = [[0, 2]], $hTimer = 0, $iArray = 5000, $iCount = 0, $iDimension = 0, $iIndexTotal = 0 $hTimer = TimerInit() ; Start the timer. For $i = 1 To $iArray If _ReDim2D_Ubound($aArray, $iDimension, $iIndexTotal) Then ; Returns 1 if ReDimmed OR 0 if it wasn't. This uses ByRef, so just pass the Array and a previously delcared variable for monbitoring the dimension and a second variable for monitoring the total count. $iCount += 1 ; If Array was ReDimmed then add to the ReDim count for output at the end. EndIf $aArray[0][0] += 1 ; Increase Index [0, 0] by 1. $aArray[$i][0] = 'Row ' & $i & ': Col 0' ; Add random data. $aArray[$i][1] = 'Row ' & $i & ': Col 1' ; Add random data. Next $hTimer = Round(TimerDiff($hTimer)) ; End the timer and find the difference from start to finish. ReDim $aArray[$aArray[0][0] + 1][$aArray[0][1]] ; Remove the empty Rows, by ReDimming the total count plus the row for holding the count and include the number of colums too. ; _ArrayDisplay($aArray) MsgBox(4096, 'How many times?', 'The amount of times a ' & $iArray & ' element array was ''ReDimmed'' was ' & $iCount & ' times.' & @CRLF & _ 'It only took ' & $hTimer & ' milliseconds to complete.') EndFunc ;==>_2D_2
Edited by guinness, 10 October 2012 - 09:05 AM.









