Ticket #2014: _Array.au3

File _Array.au3, 85.4 KB (added by BrewManNH, 11 years ago)

Modified _Array UDF (2D version)

Line 
1#include-Once
2; #INDEX# =======================================================================================================================
3; Title .........: Array
4; AutoIt Version : 3.2.10++
5; Language ......: English
6; Description ...: Functions for manipulating arrays.
7; Author(s) .....: JdeB, Erik Pilsits, Ultima, Dale (Klaatu) Thompson, Cephas,randallc, Gary Frost, GEOSoft,
8;                  Helias Gerassimou(hgeras), Brian Keene, SolidSnake, gcriaco, LazyCoder, Tylo, David Nuttall,
9;                  Adam Moore (redndahead), SmOke_N, litlmike, Valik
10; ===============================================================================================================================
11; #NO_DOC_FUNCTION# =============================================================================================================
12; Not documented - function(s) no longer needed, will be worked out of the file at a later date
13;
14;_ArrayCreate
15; ===============================================================================================================================
16; #CURRENT# =====================================================================================================================
17;_ArrayAdd *
18;_ArrayBinarySearch *
19;_ArrayCombinations
20;_ArrayConcatenate *
21;_ArrayDelete
22;_ArrayDisplay *
23;_ArrayFindAll
24;_ArrayInsert *
25;_ArrayMax *
26;_ArrayMaxIndex
27;_ArrayMin *
28;_ArrayMinIndex
29;_ArrayPermute
30;_ArrayPop *
31;_ArrayPush *
32;_ArrayReverse *
33;_ArraySearch
34;_ArraySort
35;_ArraySwap
36;_ArrayToClip *
37;_ArrayToString *
38;_ArrayTrim *
39;_ArrayUnique (Corrected the header information)
40; * - #MODIFIED FUNCTIONS#
41; ===============================================================================================================================
42; #NEW FUNCTIONS ADDED# =========================================================================================================
43;_ArrayAddColumns
44;_ArrayDeleteColumn
45;_ArrayMaxIndex2D
46;_ArrayMinIndex2D
47; ===============================================================================================================================
48; #INTERNAL_USE_ONLY# ===========================================================================================================
49;__ArrayQuickSort1D
50;__ArrayQuickSort2D
51;__Array_ExeterInternal
52;__Array_Combinations
53;__Array_GetNext
54; ===============================================================================================================================
55; #FUNCTION# ====================================================================================================================
56; Name...........: _ArrayAdd
57; Description ...: Adds a specified value at the end of an existing array. Also will add a delimited string to a 2D array.
58; Syntax.........: _ArrayAdd(ByRef $avArray, $vValue)
59; Parameters ....: $avArray - Array to modify
60;                  $vValue  - Value to add
61; Return values .: Success - Index of last added item
62;                  Failure - -1, sets @error
63;                  |1 - $avArray is not an array
64;                  |2 - $avArray is not a 1 or 2 dimensional array
65;                  |3 - $vValue has too many subitems
66; Author ........: Jos van der Zande <jdeb at autoitscript dot com>
67; Modified.......: Ultima - code cleanup, BrewManNH - 2D array support
68; Remarks .......:
69; Related .......: _ArrayConcatenate, _ArrayDelete, _ArrayInsert, _ArrayPop, _ArrayPush
70; Link ..........:
71; Example .......: Yes
72; ===============================================================================================================================
73Func _ArrayAdd(ByRef $avArray, $vValue, $sSeparator = "|")
74        If Not IsArray($avArray) Then Return SetError(1, 0, -1)
75        If UBound($avArray, 0) > 2 Then Return SetError(2, 0, -1)
76        Local $avValue = StringSplit($vValue, $sSeparator)
77        If Not @error Then
78                ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $avValue = ' & $avValue & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console
79                $iSubMax = $avValue[0]
80                If $iSubMax <> UBound($avArray, 2) Then Return SetError(3, 0, 0)
81        EndIf
82        If UBound($avArray, 0) = 1 Then
83                Local $iUBound = UBound($avArray)
84                ReDim $avArray[$iUBound + 1]
85                $avArray[$iUBound] = $vValue
86                Return $iUBound
87        Else
88                Local $iUBound = UBound($avArray)
89                ReDim $avArray[$iUBound + 1][$iSubMax]
90                For $i = 0 To $iSubMax - 1
91                        $avArray[$iUBound][$i] = $avValue[$i + 1]
92                Next
93                Return $iUBound
94        EndIf
95EndFunc   ;==>_ArrayAdd
96; #FUNCTION# ====================================================================================================================
97; Name...........: _ArrayAddColumns
98; Description ...: Adds a specified number of columns to an array.
99; Syntax.........: _ArrayAddColumns(ByRef $aArrayIn, $NumColCount)
100; Parameters ....: $aArrayIn - Array to modify
101;                  $NumColCount  - Number of columns to add (default = 1)
102; Return values .: Success - New array with columns added
103;                  Failure - -1, sets @error
104;                  |1 - $aArrayIn is not an array
105;                  |2 - $NumColCount is an invalid number
106;                  |3 - Array has too many dimensions (2D array max)
107; Author ........: Malkey
108; Remarks .......: This will add any number of columns to a 1D or 2D array of any size and preserves
109;                  the contents of the array being modified
110; Related .......: _ArrayConcatenate2D, _ArrayDelete, _ArrayInsert, _ArrayPop2D, _ArrayPush
111; Link ..........:
112; Example .......: Yes
113; ===============================================================================================================================
114Func _ArrayAddColumns(ByRef $aArr, $iNumColToAdd = 1)
115        If IsArray($aArr) = 0 Then Return SetError(1, 0, -1) ; Filter out non-array
116        If $iNumColToAdd < 1 Then Return SetError(2, 0, -1) ; $iNumColToAdd must be greater than zero to add a column.
117        If UBound($aArr, 0) > 2 Then Return SetError(3, 0, -1) ; Only allows a 1d or 2d array past this line.
118        If UBound($aArr, 0) = 1 Then ; ====== For 1d array ========
119                Local $aRet[UBound($aArr)][$iNumColToAdd + 1] ; Create new 2d array.
120                For $R = 0 To UBound($aArr) - 1
121                        $aRet[$R][0] = $aArr[$R]
122                Next
123        Else ; ======= For 2d array ============
124                Local $aRet = $aArr ; So that ByRef $aArr is not altered outside of function.
125                ReDim $aRet[UBound($aRet)][UBound($aRet, 2) + $iNumColToAdd] ; ReDim 2d array only.
126        EndIf
127        Return $aRet
128EndFunc   ;==>_ArrayAddColumns
129; #FUNCTION# ====================================================================================================================
130; Name...........: _ArrayBinarySearch
131; Description ...: Uses the binary search algorithm to search through a 1 or 2-dimensional array.
132; Syntax.........: _ArrayBinarySearch(Const ByRef $avArray, $vValue[, $iSubItem = 0[, $iStart = 0[, $iEnd = 0]]])
133; Parameters ....: $avArray - Array to search
134;                  $vValue  - Value to find
135;                  $iSubItem - [optional] Which column to search on [Default = First (0) column]
136;                  $iStart  - [optional] Index of array to start searching at [Default = start of array]
137;                  $iEnd    - [optional] Index of array to stop searching at [Default = end of array]
138; Return values .: Success - Index that value was found at
139;                  Failure - -1, sets @error to:
140;                  |1 - $avArray is not an array
141;                  |2 - $vValue outside of array's min/max values
142;                  |3 - $vValue was not found in array
143;                  |4 - $iStart is greater than $iEnd
144;                                  |5 - $iSubItem is greater than actual number of columns
145;                  |6 - $avArray has too many dimensions
146; Author ........: Jos van der Zande <jdeb at autoitscript dot com>
147; Modified.......: Ultima - added $iEnd as parameter, code cleanup
148; Modified.......: BrewManNH - added ability to search a 2D array
149; Remarks .......: When performing a binary search on an array of items, the contents of the column being searched MUST be
150;                  sorted before the search is done, otherwise undefined results will be returned.
151; Related .......: _ArrayFindAll, _ArraySearch, _ArrayBinarySearch
152; Link ..........:
153; Example .......: Yes
154; ===============================================================================================================================
155Func _ArrayBinarySearch(Const ByRef $avArray, $vValue, $iSubItem = 0, $iStart = 0, $iEnd = 0)
156        If UBound($avArray, 0) > 2 Then Return SetError(6, 0, -1)
157        Local $Is2D = False
158        If UBound($avArray, 0) > 1 Then
159                $Is2D = True
160        EndIf
161        If UBound($avArray, 2) < $iSubItem Then Return SetError(5, 0, -1)
162        If Not IsArray($avArray) Then Return SetError(1, 0, -1)
163        Local $iUBound = UBound($avArray) - 1
164        ; Bounds checking
165        If $iEnd < 1 Or $iEnd > $iUBound Then $iEnd = $iUBound
166        If $iStart < 0 Then $iStart = 0
167        If $iStart > $iEnd Then Return SetError(4, 0, -1)
168        Local $iMid = Int(($iEnd + $iStart) / 2)
169        If Not $Is2D Then
170                If $avArray[$iStart] > $vValue Or $avArray[$iEnd] < $vValue Then Return SetError(2, 0, -1)
171                ; Search
172                While $iStart <= $iMid And $vValue <> $avArray[$iMid]
173                        If $vValue < $avArray[$iMid] Then
174                                $iEnd = $iMid - 1
175                        Else
176                                $iStart = $iMid + 1
177                        EndIf
178                        $iMid = Int(($iEnd + $iStart) / 2)
179                WEnd
180                If $iStart > $iEnd Then Return SetError(3, 0, -1) ; Entry not found
181                Return $iMid
182        Else
183                If $avArray[$iStart][$iSubItem] > $vValue Or $avArray[$iEnd][$iSubItem] < $vValue Then Return SetError(2, 0, -1)
184                ; Search
185                While $iStart <= $iMid And $vValue <> $avArray[$iMid][$iSubItem]
186                        If $vValue < $avArray[$iMid][$iSubItem] Then
187                                $iEnd = $iMid - 1
188                        Else
189                                $iStart = $iMid + 1
190                        EndIf
191                        $iMid = Int(($iEnd + $iStart) / 2)
192                WEnd
193                If $iStart > $iEnd Then Return SetError(3, 0, -1) ; Entry not found
194                Return $iMid
195        EndIf
196EndFunc   ;==>_ArrayBinarySearch
197; #FUNCTION# ====================================================================================================================
198; Name...........: _ArrayCombinations
199; Description ...: Returns an Array of the Combinations of a Set of Elements from a Selected Array
200; Syntax.........: _ArrayCombinations(ByRef $avArray, $iSet[, $sDelim = ""])
201; Parameters ....: $avArray - The Array to use
202;                  $iSet - Size of the combinations set
203;                  $sDelim - [optional] String result separator, default is "" for none
204; Return values .: Success - Returns an Array of Combinations
205;                  |Returns an array, the first element ($array[0]) contains the number of strings returned.
206;                  |The remaining elements ($array[1], $array[2], etc.) contain the Combinations.
207;                  Failure - Returns 0 and Sets @error:
208;                  |1 - The Input Must be an Array
209;                  |2 - $avArray is not a 1 dimensional array
210; Author ........: Erik Pilsits
211; Modified.......: 07/08/2008
212; Remarks .......: The input array must be 0-based, i.e. no counter in $array[0]. Based on an algorithm by Kenneth H. Rosen.
213;+
214;                  http://www.merriampark.com/comb.htm
215; Related .......: _ArrayPermute
216; Link ..........:
217; Example .......: Yes
218; ==========================================================================================
219Func _ArrayCombinations(ByRef $avArray, $iSet, $sDelim = "")
220        If Not IsArray($avArray) Then Return SetError(1, 0, 0)
221        If UBound($avArray, 0) <> 1 Then Return SetError(2, 0, 0)
222        Local $iN = UBound($avArray)
223        Local $iR = $iSet
224        Local $aIdx[$iR]
225        For $i = 0 To $iR - 1
226                $aIdx[$i] = $i
227        Next
228        Local $iTotal = __Array_Combinations($iN, $iR)
229        Local $iLeft = $iTotal
230        Local $aResult[$iTotal + 1]
231        $aResult[0] = $iTotal
232        Local $iCount = 1
233        While $iLeft > 0
234                __Array_GetNext($iN, $iR, $iLeft, $iTotal, $aIdx)
235                For $i = 0 To $iSet - 1
236                        $aResult[$iCount] &= $avArray[$aIdx[$i]] & $sDelim
237                Next
238                If $sDelim <> "" Then $aResult[$iCount] = StringTrimRight($aResult[$iCount], 1)
239                $iCount += 1
240        WEnd
241        Return $aResult
242EndFunc   ;==>_ArrayCombinations
243; #FUNCTION# ====================================================================================================================
244; Name...........: _ArrayConcatenate
245; Description ...: Concatenate two arrays.
246; Syntax.........: _ArrayConcatenate(ByRef $avArrayTarget, Const ByRef $avArraySource, $iStart = 0)
247; Parameters ....: $avArrayTarget - The array to concatenate onto
248;                  $avArraySource - The array to concatenate from
249;                  $iStart - index of the first Source Array entry
250; Return values .: Success - $avArrayTarget's new size
251;                  Failure - 0, sets @error to:
252;                  |1 - $avArrayTarget is not an array
253;                  |2 - $avArraySource is not an array
254;                  |3 - $avArrayTarget is not a 1 or 2 dimensional array
255;                  |4 - $avArraySource is not a 1 or 2 dimensional array
256;                  |5 - $avArrayTarget and $avArraySource is not a 1 or 2 dimensional array
257;                  |6 - Arrays have different number of subitems
258;                  |7 - Arrays have different number of dimensions
259; Author ........: Ultima
260; Modified.......: Partypooper - added target start index
261; Remarks .......:
262; Related .......: _ArrayAdd, _ArrayPush
263; Link ..........:
264; Example .......: Yes
265; ===============================================================================================================================
266Func _ArrayConcatenate(ByRef $avArrayTarget, Const ByRef $avArraySource, $iStart = 0)
267        If Not IsArray($avArrayTarget) Then Return SetError(1, 0, 0)
268        If Not IsArray($avArraySource) Then Return SetError(2, 0, 0)
269        If UBound($avArraySource, 0) <> UBound($avArrayTarget, 0) Then Return SetError(7, 0, 0)
270        If UBound($avArrayTarget, 0) > 2 Then
271                If UBound($avArraySource, 0) > 2 Then Return SetError(5, 0, 0)
272                Return SetError(3, 0, 0)
273        EndIf
274        If UBound($avArraySource, 0) > 2 Then Return SetError(4, 0, 0)
275        If UBound($avArrayTarget, 2) <> UBound($avArraySource, 2) Then Return SetError(6, 0, 0)
276        If UBound($avArraySource, 0) = 1 Then
277                Local $iUBoundTarget = UBound($avArrayTarget) - $iStart, $iUBoundSource = UBound($avArraySource)
278                ReDim $avArrayTarget[$iUBoundTarget + $iUBoundSource]
279                For $i = $iStart To $iUBoundSource - 1
280                        $avArrayTarget[$iUBoundTarget + $i] = $avArraySource[$i]
281                Next
282                Return $iUBoundTarget + $iUBoundSource
283        Else
284                Local $iUBoundTarget = UBound($avArrayTarget) - $iStart, $iUBoundSource = UBound($avArraySource), $iSubItems = UBound($avArrayTarget, 2)
285                ReDim $avArrayTarget[$iUBoundTarget + $iUBoundSource][$iSubItems]
286                For $i = $iStart To $iUBoundSource - 1
287                        For $x = 0 To $iSubItems - 1
288                                $avArrayTarget[$iUBoundTarget + $i][$x] = $avArraySource[$i][$x]
289                        Next
290                Next
291                Return $iUBoundTarget + $iUBoundSource
292        EndIf
293EndFunc   ;==>_ArrayConcatenate
294; #NO_DOC_FUNCTION# =============================================================================================================
295; Name...........: _ArrayCreate
296; Description ...: Create a small array and quickly assign values.
297; Syntax.........: _ArrayCreate ($v_0 [,$v_1 [,... [, $v_20 ]]])
298; Parameters ....: $v_0  - The first element of the array
299;                  $v_1  - [optional] The second element of the array
300;                  ...
301;                  $v_20 - [optional] The twenty-first element of the array
302; Return values .: Success - The array with values
303; Author ........: Dale (Klaatu) Thompson, Jos van der Zande <jdeb at autoitscript dot com> - rewritten to avoid Eval() errors in Obsufcator
304; Modified.......: Ultima
305; Remarks .......: Arrays of up to 21 elements in size can be created with this function.
306; Related .......:
307; Link ..........:
308; Example .......: Yes
309; ===============================================================================================================================
310Func _ArrayCreate($v_0, $v_1 = 0, $v_2 = 0, $v_3 = 0, $v_4 = 0, $v_5 = 0, $v_6 = 0, $v_7 = 0, $v_8 = 0, $v_9 = 0, $v_10 = 0, $v_11 = 0, $v_12 = 0, $v_13 = 0, $v_14 = 0, $v_15 = 0, $v_16 = 0, $v_17 = 0, $v_18 = 0, $v_19 = 0, $v_20 = 0)
311        Local $av_Array[21] = [$v_0, $v_1, $v_2, $v_3, $v_4, $v_5, $v_6, $v_7, $v_8, $v_9, $v_10, $v_11, $v_12, $v_13, $v_14, $v_15, $v_16, $v_17, $v_18, $v_19, $v_20]
312        ReDim $av_Array[@NumParams]
313        Return $av_Array
314EndFunc   ;==>_ArrayCreate
315; #FUNCTION# ====================================================================================================================
316; Name...........: _ArrayDelete
317; Description ...: Deletes the specified element from the given array.
318; Syntax.........: _ArrayDelete(ByRef $avArray, $iElement)
319; Parameters ....: $avArray  - Array to modify
320;                  $iElement - Element to delete
321; Return values .: Success - New size of the array
322;                  Failure - 0, sets @error to:
323;                  |1 - $avArray is not an array
324;                  |3 - $avArray has too many dimensions (only up to 2D supported)
325;                  |(2 - Deprecated error code)
326; Author ........: Cephas <cephas at clergy dot net>
327; Modified.......: Jos van der Zande <jdeb at autoitscript dot com> - array passed ByRef, Ultima - 2D arrays supported, reworked function (no longer needs temporary array; faster when deleting from end)
328; Remarks .......: If the array has one element left (or one row for 2D arrays), it will be set to "" after _ArrayDelete() is used on it.
329;+
330;                  If the $ilement is greater than the array size then the last element is destroyed.
331; Related .......: _ArrayAdd, _ArrayInsert, _ArrayPop, _ArrayPush
332; Link ..........:
333; Example .......: Yes
334; ===============================================================================================================================
335Func _ArrayDelete(ByRef $avArray, $iElement)
336        If Not IsArray($avArray) Then Return SetError(1, 0, 0)
337        Local $iUBound = UBound($avArray, 1) - 1
338        If Not $iUBound Then
339                $avArray = ""
340                Return 0
341        EndIf
342        ; Bounds checking
343        If $iElement < 0 Then $iElement = 0
344        If $iElement > $iUBound Then $iElement = $iUBound
345        ; Move items after $iElement up by 1
346        Switch UBound($avArray, 0)
347                Case 1
348                        For $i = $iElement To $iUBound - 1
349                                $avArray[$i] = $avArray[$i + 1]
350                        Next
351                        ReDim $avArray[$iUBound]
352                Case 2
353                        Local $iSubMax = UBound($avArray, 2) - 1
354                        For $i = $iElement To $iUBound - 1
355                                For $j = 0 To $iSubMax
356                                        $avArray[$i][$j] = $avArray[$i + 1][$j]
357                                Next
358                        Next
359                        ReDim $avArray[$iUBound][$iSubMax + 1]
360                Case Else
361                        Return SetError(3, 0, 0)
362        EndSwitch
363        Return $iUBound
364EndFunc   ;==>_ArrayDelete
365; #FUNCTION# ====================================================================================================================
366; Name...........: _ArrayDeleteColumn
367; Description ...: Deletes a specified column from a 2D array.
368; Syntax.........: _ArrayDeleteColumn(ByRef $aArrayIn, $iSubItem)
369; Parameters ....: $aArrayIn - Array to modify
370;                  $iSubItem  - The column to delete
371; Return values .: Success - New array with column deleted
372;                  Failure - -1, sets @error
373;                  |1 - $aArrayIn is not an array
374;                  |2 - Array is not a 2D array
375;                  |3 - $iSubItem is an invalid number
376; Author ........: PsaltyDS
377; Remarks .......: This will delete a column from a 2D array of any size and preserves the contents of the
378;                  array being modified
379; Notes .........: This will NOT create a 1D array from a 2D array even if your final array contains only 1 column
380;                  this is because the final array will be dimensioned as a 2D array with the second subitem dimensioned
381;                  to zero.
382; Related .......: _ArrayConcatenate2D, _ArrayDelete, _ArrayInsert, _ArrayPop2D, _ArrayPush, _ArrayAddColumn
383; Link ..........:
384; Example .......: No
385; ===============================================================================================================================
386Func _ArrayDeleteColumn(ByRef $aArrayIn, $iSubItem)
387        If Not IsArray($aArrayIn) Then Return SetError(1, 0, -1); Not an array
388        If UBound($aArrayIn, 0) <> 2 Then Return SetError(2, 0, -1); Not a 2D array
389        If ($iSubItem < 0) Or ($iSubItem > (UBound($aArrayIn, 2) - 1)) Then Return SetError(3, 0, -1); $iSubItem out of range
390        If $iSubItem < UBound($aArrayIn, 2) - 1 Then
391                For $c = $iSubItem To UBound($aArrayIn, 2) - 2
392                        For $R = 0 To UBound($aArrayIn) - 1
393                                $aArrayIn[$R][$c] = $aArrayIn[$R][$c + 1]
394                        Next
395                Next
396        EndIf
397        ReDim $aArrayIn[UBound($aArrayIn)][UBound($aArrayIn, 2) - 1]
398        Return 1
399EndFunc   ;==>_ArrayDeleteColumn
400; #FUNCTION# ====================================================================================================================
401; Name...........: _ArrayDisplay
402; Description ...: Displays given 1D or 2D array array in a listview.
403; Syntax.........: _ArrayDisplay(Const ByRef $avArray[, $sTitle = "Array: ListView Display"[, $iItemLimit = -1[, $iTranspose = 0[, $sSeparator = ""[, $sReplace = "|"[, $sHeader = ""]]]]]])
404; Parameters ....: $avArray    - Array to display
405;                  $sTitle     - [optional] Title to use for window
406;                  $iItemLimit - [optional] Maximum number of listview items (rows) to show
407;                  $iTranspose - [optional] If set differently than default, will transpose the array if 2D
408;                  $sSeparator - [optional] Change Opt("GUIDataSeparatorChar") on-the-fly
409;                  $sReplace   - [optional] String to replace any occurrence of $sSeparator with in each array element
410;                  $sheader     - [optional] Header column names
411; Return values .: Success - 1
412;                  Failure - 0, sets @error:
413;                  |1 - $avArray is not an array
414;                  |2 - $avArray has too many dimensions (only up to 2D supported)
415; Author ........: randallc, Ultima
416; Modified.......: Gary Frost (gafrost), Ultima, Zedna, jpm, BrewManNH
417; Remarks .......: This will now autosize the GUI Window and autosize the column widths to match the longest items
418; Related .......:
419; Link ..........:
420; Example .......: Yes
421; ===============================================================================================================================
422Func _ArrayDisplay(Const ByRef $avArray, $sTitle = "Array: ListView Display", $iItemLimit = -1, $iTranspose = 0, $sSeparator = "", $sReplace = "|", $sHeader = "")
423        If Not IsArray($avArray) Then Return SetError(1, 0, 0)
424        ; Dimension checking
425        Local $iDimension = UBound($avArray, 0), $iUBound = UBound($avArray, 1) - 1, $iSubMax = UBound($avArray, 2) - 1
426        If $iDimension > 2 Then Return SetError(2, 0, 0)
427        ; Separator handling
428;~     If $sSeparator = "" Then $sSeparator = Chr(1)
429        If $sSeparator = "" Then $sSeparator = Chr(124)
430        ;  Check the separator to make sure it's not used literally in the array
431        If _ArraySearch($avArray, $sSeparator, 0, 0, 0, 1) <> -1 Then
432                For $x = 1 To 255
433                        If $x >= 32 And $x <= 127 Then ContinueLoop
434                        Local $sFind = _ArraySearch($avArray, Chr($x), 0, 0, 0, 1)
435                        If $sFind = -1 Then
436                                $sSeparator = Chr($x)
437                                ExitLoop
438                        EndIf
439                Next
440        EndIf
441        ; Declare variables
442        Local $vTmp, $iBuffer = 64
443        Local $iColLimit = 250
444        Local $iOnEventMode = Opt("GUIOnEventMode", 0), $sDataSeparatorChar = Opt("GUIDataSeparatorChar", $sSeparator)
445        ; Swap dimensions if transposing
446        If $iSubMax < 0 Then $iSubMax = 0
447        If $iTranspose Then
448                $vTmp = $iUBound
449                $iUBound = $iSubMax
450                $iSubMax = $vTmp
451        EndIf
452        ; Set limits for dimensions
453        If $iSubMax > $iColLimit Then $iSubMax = $iColLimit
454        If $iItemLimit < 1 Then $iItemLimit = $iUBound
455        If $iUBound > $iItemLimit Then $iUBound = $iItemLimit
456        ; Set header up
457        If $sHeader = "" Then
458                $sHeader = "Row  " ; blanks added to adjust column size for big number of rows
459                For $i = 0 To $iSubMax
460                        $sHeader &= $sSeparator & "Col " & $i
461                Next
462        EndIf
463        ; Convert array into text for listview
464        Local $avArrayText[$iUBound + 1]
465        For $i = 0 To $iUBound
466                $avArrayText[$i] = "[" & $i & "]"
467                For $j = 0 To $iSubMax
468                        ; Get current item
469                        If $iDimension = 1 Then
470                                If $iTranspose Then
471                                        $vTmp = $avArray[$j]
472                                Else
473                                        $vTmp = $avArray[$i]
474                                EndIf
475                        Else
476                                If $iTranspose Then
477                                        $vTmp = $avArray[$j][$i]
478                                Else
479                                        $vTmp = $avArray[$i][$j]
480                                EndIf
481                        EndIf
482                        ; Add to text array
483                        $vTmp = StringReplace($vTmp, $sSeparator, $sReplace, 0, 1)
484                        $avArrayText[$i] &= $sSeparator & $vTmp
485                        ; Set max buffer size
486                        $vTmp = StringLen($vTmp)
487                        If $vTmp > $iBuffer Then $iBuffer = $vTmp
488                Next
489        Next
490        $iBuffer += 1
491        ; GUI Constants
492        Local Const $_ARRAYCONSTANT_GUI_DOCKBORDERS = 0x66
493        Local Const $_ARRAYCONSTANT_GUI_DOCKBOTTOM = 0x40
494        Local Const $_ARRAYCONSTANT_GUI_DOCKHEIGHT = 0x0200
495        Local Const $_ARRAYCONSTANT_GUI_DOCKLEFT = 0x2
496        Local Const $_ARRAYCONSTANT_GUI_DOCKRIGHT = 0x4
497        Local Const $_ARRAYCONSTANT_GUI_EVENT_CLOSE = -3
498        Local Const $_ARRAYCONSTANT_LVIF_PARAM = 0x4
499        Local Const $_ARRAYCONSTANT_LVIF_TEXT = 0x1
500        Local Const $_ARRAYCONSTANT_LVM_GETCOLUMNWIDTH = (0x1000 + 29)
501        Local Const $_ARRAYCONSTANT_LVM_GETITEMCOUNT = (0x1000 + 4)
502        Local Const $_ARRAYCONSTANT_LVM_GETITEMSTATE = (0x1000 + 44)
503        Local Const $_ARRAYCONSTANT_LVM_INSERTITEMW = (0x1000 + 77)
504        Local Const $_ARRAYCONSTANT_LVM_SETEXTENDEDLISTVIEWSTYLE = (0x1000 + 54)
505        Local Const $_ARRAYCONSTANT_LVM_SETITEMW = (0x1000 + 76)
506        Local Const $_ARRAYCONSTANT_LVS_EX_FULLROWSELECT = 0x20
507        Local Const $_ARRAYCONSTANT_LVS_EX_GRIDLINES = 0x1
508        Local Const $_ARRAYCONSTANT_LVS_SHOWSELALWAYS = 0x8
509        Local Const $_ARRAYCONSTANT_WS_EX_CLIENTEDGE = 0x0200
510        Local Const $_ARRAYCONSTANT_WS_MAXIMIZEBOX = 0x00010000
511        Local Const $_ARRAYCONSTANT_WS_MINIMIZEBOX = 0x00020000
512        Local Const $_ARRAYCONSTANT_WS_SIZEBOX = 0x00040000
513        Local Const $_ARRAYCONSTANT_tagLVITEM = "int Mask;int Item;int SubItem;int State;int StateMask;ptr Text;int TextMax;int Image;int Param;int Indent;int GroupID;int Columns;ptr pColumns"
514        Local $iAddMask = BitOR($_ARRAYCONSTANT_LVIF_TEXT, $_ARRAYCONSTANT_LVIF_PARAM)
515        Local $tBuffer = DllStructCreate("wchar Text[" & $iBuffer & "]"), $pBuffer = DllStructGetPtr($tBuffer)
516        Local $tItem = DllStructCreate($_ARRAYCONSTANT_tagLVITEM), $pItem = DllStructGetPtr($tItem)
517        DllStructSetData($tItem, "Param", 0)
518        DllStructSetData($tItem, "Text", $pBuffer)
519        DllStructSetData($tItem, "TextMax", $iBuffer)
520        ; Set interface up
521        Local $iWidth = 640, $iHeight = 480
522        Local $hGUI = GUICreate($sTitle, $iWidth, $iHeight, Default, Default, BitOR($_ARRAYCONSTANT_WS_SIZEBOX, $_ARRAYCONSTANT_WS_MINIMIZEBOX, $_ARRAYCONSTANT_WS_MAXIMIZEBOX))
523        Local $aiGUISize = WinGetClientSize($hGUI)
524        Local $hListView = GUICtrlCreateListView($sHeader, 0, 0, $aiGUISize[0], $aiGUISize[1] - 26, $_ARRAYCONSTANT_LVS_SHOWSELALWAYS)
525        Local $hCopy = GUICtrlCreateButton("Copy Selected", 3, $aiGUISize[1] - 23, $aiGUISize[0] - 6, 20)
526        GUICtrlSetResizing($hListView, $_ARRAYCONSTANT_GUI_DOCKBORDERS)
527        GUICtrlSetResizing($hCopy, $_ARRAYCONSTANT_GUI_DOCKLEFT + $_ARRAYCONSTANT_GUI_DOCKRIGHT + $_ARRAYCONSTANT_GUI_DOCKBOTTOM + $_ARRAYCONSTANT_GUI_DOCKHEIGHT)
528        GUICtrlSendMsg($hListView, $_ARRAYCONSTANT_LVM_SETEXTENDEDLISTVIEWSTYLE, $_ARRAYCONSTANT_LVS_EX_GRIDLINES, $_ARRAYCONSTANT_LVS_EX_GRIDLINES)
529        GUICtrlSendMsg($hListView, $_ARRAYCONSTANT_LVM_SETEXTENDEDLISTVIEWSTYLE, $_ARRAYCONSTANT_LVS_EX_FULLROWSELECT, $_ARRAYCONSTANT_LVS_EX_FULLROWSELECT)
530        GUICtrlSendMsg($hListView, $_ARRAYCONSTANT_LVM_SETEXTENDEDLISTVIEWSTYLE, $_ARRAYCONSTANT_WS_EX_CLIENTEDGE, $_ARRAYCONSTANT_WS_EX_CLIENTEDGE)
531        ; Fill listview
532        Local $aItem
533        For $i = 0 To $iUBound
534                If GUICtrlCreateListViewItem($avArrayText[$i], $hListView) = 0 Then
535                        ; use GUICtrlSendMsg() to overcome AutoIt limitation
536                        $aItem = StringSplit($avArrayText[$i], $sSeparator)
537                        DllStructSetData($tBuffer, "Text", $aItem[1])
538                        ; Add listview item
539                        DllStructSetData($tItem, "Item", $i)
540                        DllStructSetData($tItem, "SubItem", 0)
541                        DllStructSetData($tItem, "Mask", $iAddMask)
542                        GUICtrlSendMsg($hListView, $_ARRAYCONSTANT_LVM_INSERTITEMW, 0, $pItem)
543                        ; Set listview subitem text
544                        DllStructSetData($tItem, "Mask", $_ARRAYCONSTANT_LVIF_TEXT)
545                        For $j = 2 To $aItem[0]
546                                DllStructSetData($tBuffer, "Text", $aItem[$j])
547                                DllStructSetData($tItem, "SubItem", $j - 1)
548                                GUICtrlSendMsg($hListView, $_ARRAYCONSTANT_LVM_SETITEMW, 0, $pItem)
549                        Next
550                EndIf
551        Next
552;~  <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< added lines in this section
553;~
554        ; adjust column size to match longest item in the list
555        GUICtrlSendMsg($hListView, 4126, 1, -1)
556        If $iDimension = 2 Then
557                For $i = 2 To UBound($avArray, 2)
558                        GUICtrlSendMsg($hListView, 4126, $i, -1)
559                Next
560        EndIf
561;~  <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< added lines in this section
562;~
563        ; adjust window width
564        $iWidth = 0
565        For $i = 0 To $iSubMax + 1
566                $iWidth += GUICtrlSendMsg($hListView, $_ARRAYCONSTANT_LVM_GETCOLUMNWIDTH, $i, 0)
567        Next
568        If $iWidth < 250 Then $iWidth = 230
569        $iWidth += 40 ;~ <<<<<<<<<<<<<<<<<<<<<< Changed this value from 20 to 40
570        If $iWidth > @DesktopWidth Then $iWidth = @DesktopWidth - 100
571        WinMove($hGUI, "", (@DesktopWidth - $iWidth) / 2, Default, $iWidth)
572        ; Show dialog
573        GUISetState(@SW_SHOW, $hGUI)
574        While 1
575                Switch GUIGetMsg()
576                        Case $_ARRAYCONSTANT_GUI_EVENT_CLOSE
577                                ExitLoop
578                        Case $hCopy
579                                Local $sClip = ""
580                                ; Get selected indices [ _GUICtrlListView_GetSelectedIndices($hListView, True) ]
581                                Local $aiCurItems[1] = [0]
582                                For $i = 0 To GUICtrlSendMsg($hListView, $_ARRAYCONSTANT_LVM_GETITEMCOUNT, 0, 0)
583                                        If GUICtrlSendMsg($hListView, $_ARRAYCONSTANT_LVM_GETITEMSTATE, $i, 0x2) Then
584                                                $aiCurItems[0] += 1
585                                                ReDim $aiCurItems[$aiCurItems[0] + 1]
586                                                $aiCurItems[$aiCurItems[0]] = $i
587                                        EndIf
588                                Next
589                                ; Generate clipboard text
590                                If Not $aiCurItems[0] Then
591                                        For $sItem In $avArrayText
592                                                $sClip &= $sItem & @CRLF
593                                        Next
594                                Else
595                                        For $i = 1 To UBound($aiCurItems) - 1
596                                                $sClip &= $avArrayText[$aiCurItems[$i]] & @CRLF
597                                        Next
598                                EndIf
599                                ClipPut($sClip)
600                EndSwitch
601        WEnd
602        GUIDelete($hGUI)
603        Opt("GUIOnEventMode", $iOnEventMode)
604        Opt("GUIDataSeparatorChar", $sDataSeparatorChar)
605        Return 1
606EndFunc   ;==>_ArrayDisplay
607; #FUNCTION# ====================================================================================================================
608; Name...........: _ArrayFindAll
609; Description ...: Find the indices of all ocurrences of a search query between two points in a 1D or 2D array using _ArraySearch().
610; Syntax.........: _ArrayFindAll(Const ByRef $avArray, $vValue[, $iStart = 0[, $iEnd = 0[, $iCase = 0[, $iPartial = 0[, $iSubItem = 0]]]]])
611; Parameters ....: $avArray  - The array to search
612;                  $vValue   - What to search $avArray for
613;                  $iStart   - [optional] Index of array to start searching at
614;                  $iEnd     - [optional] Index of array to stop searching at
615;                  $iCase    - [optional] If set to 1, search is case sensitive
616;                  $iPartial - [optional] If set to 1, executes a partial search
617;                  $iSubItem - [optional] Sub-index to search on in 2D arrays
618; Return values .: Success - An array of all index numbers in array containing $vValue
619;                  Failure - -1, sets @error (see _ArraySearch() description for error codes)
620; Author ........: GEOSoft, Ultima
621; Modified.......:
622; Remarks .......:
623; Related .......: _ArrayBinarySearch, _ArraySearch
624; Link ..........:
625; Example .......: Yes
626; ===============================================================================================================================
627Func _ArrayFindAll(Const ByRef $avArray, $vValue, $iStart = 0, $iEnd = 0, $iCase = 0, $iPartial = 0, $iSubItem = 0)
628        $iStart = _ArraySearch($avArray, $vValue, $iStart, $iEnd, $iCase, $iPartial, 1, $iSubItem)
629        If @error Then Return SetError(@error, 0, -1)
630        Local $iIndex = 0, $avResult[UBound($avArray)]
631        Do
632                $avResult[$iIndex] = $iStart
633                $iIndex += 1
634                $iStart = _ArraySearch($avArray, $vValue, $iStart + 1, $iEnd, $iCase, $iPartial, 1, $iSubItem)
635        Until @error
636        ReDim $avResult[$iIndex]
637        Return $avResult
638EndFunc   ;==>_ArrayFindAll
639; #FUNCTION# ====================================================================================================================
640; Name...........: _ArrayInsert
641; Description ...: Add a new value at the specified position.
642; Syntax.........: _ArrayInsert(ByRef $avArray, $iElement[, $vValue = ""[, $sDelim = "|"]])
643; Parameters ....: $avArray  - Array to modify
644;                  $iElement - Position to insert item at:
645;                                If $iElement <= 0 then item will be inserted at the start of the array
646;                                If $iElement > than the size of the array, the item will be added to the end of the array.
647;                  $vValue   - [optional] Value of item to insert
648;                  $sDelim       - [optional] Delimiter character to split incoming string on, default is | character
649; Return values .: Success - New size of the array
650;                  Failure - 0, sets @error
651;                  |1 - $avArray is not an array
652;                  |2 - $avArray is not a 1 or 2 dimensional array
653;                  |3 - $vValue has different number of subitems than $avArray, when using a 2D array.
654; Author ........: Jos van der Zande <jdeb at autoitscript dot com>
655; Modified.......: Ultima - code cleanup
656; Modified.......: BrewManNH - Added 2D array support
657; Remarks .......:
658; Related .......: _ArrayAdd, _ArrayDelete, _ArrayPop, _ArrayPush
659; Link ..........:
660; Example .......: Yes
661; ===============================================================================================================================
662Func _ArrayInsert(ByRef $avArray, $iElement, $vValue = "", $sDelim = "|")
663        If Not IsArray($avArray) Then Return SetError(1, 0, 0)
664        If UBound($avArray, 0) > 2 Then Return SetError(2, 0, 0)
665        If $iElement > UBound($avArray) Then $iElement = UBound($avArray)
666        If $iElement < 0 Then $iElement = 0
667        ; Add 1 to the array
668        Local $iUBound = UBound($avArray) + 1, $iMaxSubItems = UBound($avArray, 2), $iDimension = UBound($avArray, 0)
669        If $iDimension = 1 Then
670                ReDim $avArray[$iUBound]
671                ; Move all entries over til the specified element
672                For $i = $iUBound - 1 To $iElement + 1 Step -1
673                        $avArray[$i] = $avArray[$i - 1]
674                Next
675                ; Add the value in the specified element
676                $avArray[$iElement] = $vValue
677                Return $iUBound
678        Else
679                ReDim $avArray[$iUBound][$iMaxSubItems]
680                Local $avValue = StringSplit($vValue, $sDelim, 2)
681                If UBound($avValue) <> $iMaxSubItems Then Return SetError(3, 0, 0)
682                For $i = $iUBound - 1 To $iElement + 1 Step -1
683                        For $j = 0 To $iMaxSubItems - 1
684                                $avArray[$i][$j] = $avArray[$i - 1][$j]
685                        Next
686                Next
687                ; Add the value in the specified element
688                For $j = 0 To $iMaxSubItems - 1
689                        $avArray[$iElement][$j] = $avValue[$j]
690                Next
691                Return $iUBound
692        EndIf
693EndFunc   ;==>_ArrayInsert
694; #FUNCTION# ====================================================================================================================
695; Name...........: _ArrayMax
696; Description ...: Returns the highest value held in an array.
697; Syntax.........: _ArrayMax(Const ByRef $avArray[, $iCompNumeric = 0[, $iStart = 0[, $iEnd = 0[, $iSubItem = 0]]]])
698; Parameters ....: $avArray      - Array to search
699;                  $iCompNumeric - [optional] Comparison method:
700;                  |0 - compare alphanumerically
701;                  |1 - compare numerically
702;                  $iStart       - [optional] Index of array to start searching at
703;                  $iEnd         - [optional] Index of array to stop searching at
704;                  $iSubItem     - [optional] Subitem to search (first subitem is 0)
705; Return values .: Success - The maximum value in the array
706;                  Failure - "", sets @error (see _ArrayMaxIndex() description for error codes)
707; Author ........: Cephas <cephas at clergy dot net>
708; Modified.......: Jos van der Zande <jdeb at autoitscript dot com> - Added $iCompNumeric and $iStart parameters and logic, Ultima - added $iEnd parameter, code cleanup
709; Modified.......: BrewManNH - Added 2D array support
710; Remarks .......:
711; Related .......: _ArrayMaxIndex, _ArrayMin, _ArrayMinIndex, _ArrayUnique
712; Link ..........:
713; Example .......: Yes
714; ===============================================================================================================================
715Func _ArrayMax(Const ByRef $avArray, $iCompNumeric = 0, $iStart = 0, $iEnd = 0, $iSubItem = 0)
716        If $iSubItem > UBound($avArray, 2) - 1 Then $iSubItem = UBound($avArray, 2) - 1
717        If $iSubItem < 1 Then $iSubItem = 0
718        If UBound($avArray, 0) = 1 Then
719                Local $iResult = _ArrayMaxIndex($avArray, $iCompNumeric, $iStart, $iEnd)
720                If @error Then Return SetError(@error, 0, "")
721                Return $avArray[$iResult]
722        Else
723                Local $iResult = _ArrayMaxIndex2D($avArray, $iCompNumeric, $iStart, $iEnd, $iSubItem)
724                If @error Then Return SetError(@error, 0, "")
725                Return $avArray[$iResult][$iSubItem]
726        EndIf
727EndFunc   ;==>_ArrayMax
728; #FUNCTION# ====================================================================================================================
729; Name...........: _ArrayMaxIndex
730; Description ...: Returns the index where the highest value occurs in the array.
731; Syntax.........: _ArrayMaxIndex(Const ByRef $avArray[, $iCompNumeric = 0[, $iStart = 0[, $iEnd = 0]]])
732; Parameters ....: $avArray      - Array to search
733;                  $iCompNumeric - [optional] Comparison method:
734;                  |0 - compare alphanumerically
735;                  |1 - compare numerically
736;                  $iStart       - [optional] Index of array to start searching at
737;                  $iEnd         - [optional] Index of array to stop searching at
738; Return values .: Success - The index of the maximum value in the array
739;                  Failure - -1, sets @error to:
740;                  |1 - $avArray is not an array
741;                  |2 - $iStart is greater than $iEnd
742;                  |3 - $avArray is not a 1 dimensional array
743; Author ........: Cephas <cephas at clergy dot net>
744; Modified.......: Jos van der Zande <jdeb at autoitscript dot com> - Added $iCompNumeric and $iStart parameters and logic, Ultima - added $iEnd parameter, code cleanup, optimization
745; Remarks .......:
746; Related .......: _ArrayMax, _ArrayMin, _ArrayMinIndex
747; Link ..........:
748; Example .......: Yes
749; ===============================================================================================================================
750Func _ArrayMaxIndex(Const ByRef $avArray, $iCompNumeric = 0, $iStart = 0, $iEnd = 0)
751        If Not IsArray($avArray) Or UBound($avArray, 0) <> 1 Then Return SetError(1, 0, -1)
752        If UBound($avArray, 0) <> 1 Then Return SetError(3, 0, -1)
753        Local $iUBound = UBound($avArray) - 1
754        ; Bounds checking
755        If $iEnd < 1 Or $iEnd > $iUBound Then $iEnd = $iUBound
756        If $iStart < 0 Then $iStart = 0
757        If $iStart > $iEnd Then Return SetError(2, 0, -1)
758        Local $iMaxIndex = $iStart
759        ; Search
760        If $iCompNumeric Then
761                For $i = $iStart To $iEnd
762                        If Number($avArray[$iMaxIndex]) < Number($avArray[$i]) Then $iMaxIndex = $i
763                Next
764        Else
765                For $i = $iStart To $iEnd
766                        If $avArray[$iMaxIndex] < $avArray[$i] Then $iMaxIndex = $i
767                Next
768        EndIf
769        Return $iMaxIndex
770EndFunc   ;==>_ArrayMaxIndex
771; #FUNCTION# ====================================================================================================================
772; Name...........: _ArrayMaxIndex2D
773; Description ...: Returns the index where the highest value occurs in the array.
774; Syntax.........: _ArrayMax2DIndex(Const ByRef $avArray[, $iCompNumeric = 0[, $iStart = 0[, $iEnd = 0[, $iSubItem = ]]]])
775; Parameters ....: $avArray      - Array to search
776;                  $iCompNumeric - [optional] Comparison method:
777;                  |0 - compare alphanumerically
778;                  |1 - compare numerically
779;                  $iStart       - [optional] Index of array to start searching at
780;                  $iEnd         - [optional] Index of array to stop searching at
781;                  $iSubItem     - [optional] Subitem to search
782; Return values .: Success - The index of the maximum value in the array
783;                  Failure - -1, sets @error to:
784;                  |1 - $avArray is not an array
785;                  |2 - $iStart is greater than $iEnd
786;                  |3 - $avArray is not a 2 dimensional array
787; Author ........: Cephas <cephas at clergy dot net>
788; Modified.......: Jos van der Zande <jdeb at autoitscript dot com> - Added $iCompNumeric and $iStart parameters and logic, Ultima - added $iEnd parameter, code cleanup, optimization
789; Modified.......: BrewManNH - Added 2D array support
790; Remarks .......: This a modified version of _ArrayMaxIndex which adds support for 2D arrays.
791; Related .......: _ArrayMax, _ArrayMin, _ArrayMaxIndex
792; Link ..........:
793; Example .......: Yes
794; ===============================================================================================================================
795Func _ArrayMaxIndex2D(Const ByRef $avArray, $iCompNumeric = 0, $iStart = 0, $iEnd = 0, $iSubItem = 0)
796        If Not IsArray($avArray) Or UBound($avArray, 0) <> 2 Then Return SetError(1, 0, -1)
797        If UBound($avArray, 0) <> 2 Then Return SetError(3, 0, -1)
798        Local $iUBound = UBound($avArray) - 1
799        ; Bounds checking
800        If $iEnd < 1 Or $iEnd > $iUBound Then $iEnd = $iUBound
801        If $iSubItem > UBound($avArray, 2) - 1 Then $iSubItem = UBound($avArray, 2) - 1
802        If $iSubItem < 1 Then $iSubItem = 0
803        If $iStart < 0 Then $iStart = 0
804        If $iStart > $iEnd Then Return SetError(2, 0, -1)
805        Local $iMaxIndex = $iStart
806        ; Search
807        If $iCompNumeric Then
808                For $i = $iStart To $iEnd
809                        If Number($avArray[$iMaxIndex][$iSubItem]) < Number($avArray[$i][$iSubItem]) Then $iMaxIndex = $i
810                Next
811        Else
812                For $i = $iStart To $iEnd
813                        If $avArray[$iMaxIndex][$iSubItem] < $avArray[$i][$iSubItem] Then $iMaxIndex = $i
814                Next
815        EndIf
816        Return $iMaxIndex
817EndFunc   ;==>_ArrayMaxIndex2D
818; #FUNCTION# ====================================================================================================================
819; Name...........: _ArrayMin
820; Description ...: Returns the lowest value held in an array.
821; Syntax.........: _ArrayMin(Const ByRef $avArray[, $iCompNumeric = 0[, $iStart = 0[, $iEnd = 0[, $iSubItem = 0]]]])
822; Parameters ....: $avArray      - Array to search
823;                  $iCompNumeric - [optional] Comparison method:
824;                  |0 - compare alphanumerically
825;                  |1 - compare numerically
826;                  $iStart       - [optional] Index of array to start searching at
827;                  $iEnd         - [optional] Index of array to stop searching at
828;                  $iSubItem     - [optional] Subitem to search
829; Return values .: Success - The minimum value in the array
830;                  Failure - "", sets @error (see _ArrayMinIndex2D() description for error codes)
831; Author ........: Cephas <cephas at clergy dot net>
832; Modified.......: Jos van der Zande <jdeb at autoitscript dot com> - Added $iCompNumeric and $iStart parameters and logic, Ultima - added $iEnd parameter, code cleanup
833; Modified.......: BrewManNH - Added 2D array support
834; Remarks .......:
835; Related .......: _ArrayMax2D, _ArrayMax2DIndex, _ArrayMinIndex2D, _ArrayUnique
836; Link ..........:
837; Example .......: Yes
838; ===============================================================================================================================
839Func _ArrayMin(Const ByRef $avArray, $iCompNumeric = 0, $iStart = 0, $iEnd = 0, $iSubItem = 0)
840        If $iSubItem > UBound($avArray, 2) - 1 Then $iSubItem = UBound($avArray, 2) - 1
841        If $iSubItem < 1 Then $iSubItem = 0
842        If UBound($avArray, 0) = 1 Then
843                Local $iResult = _ArrayMinIndex($avArray, $iCompNumeric, $iStart, $iEnd)
844                If @error Then Return SetError(@error, 0, "")
845                Return $avArray[$iResult]
846        Else
847                Local $iResult = _ArrayMinIndex2D($avArray, $iCompNumeric, $iStart, $iEnd, $iSubItem)
848                If @error Then Return SetError(@error, 0, "")
849                Return $avArray[$iResult][$iSubItem]
850        EndIf
851EndFunc   ;==>_ArrayMin
852; #FUNCTION# ====================================================================================================================
853; Name...........: _ArrayMinIndex
854; Description ...: Returns the index where the lowest value occurs in the array.
855; Syntax.........: _ArrayMinIndex(Const ByRef $avArray[, $iCompNumeric = 0[, $iStart = 0[, $iEnd = 0]]])
856; Parameters ....: $avArray      - Array to search
857;                  $iCompNumeric - [optional] Comparison method:
858;                  |0 - compare alphanumerically
859;                  |1 - compare numerically
860;                  $iStart       - [optional] Index of array to start searching at
861;                  $iEnd         - [optional] Index of array to stop searching at
862; Return values .: Success - The index of the minimum value in the array
863;                  Failure - -1, sets @error to:
864;                  |1 - $avArray is not an array
865;                  |2 - $iStart is greater than $iEnd
866;                  |3 - $avArray is not a 1 dimensional array
867; Author ........: Cephas <cephas at clergy dot net>
868; Modified.......: Jos van der Zande <jdeb at autoitscript dot com> - Added $iCompNumeric and $iStart parameters and logic, Ultima - added $iEnd parameter, code cleanup, optimization
869; Remarks .......:
870; Related .......: _ArrayMax, _ArrayMaxIndex, _ArrayMin
871; Link ..........:
872; Example .......: Yes
873; ===============================================================================================================================
874Func _ArrayMinIndex(Const ByRef $avArray, $iCompNumeric = 0, $iStart = 0, $iEnd = 0)
875        If Not IsArray($avArray) Then Return SetError(1, 0, -1)
876        If UBound($avArray, 0) <> 1 Then Return SetError(3, 0, -1)
877        Local $iUBound = UBound($avArray) - 1
878        ; Bounds checking
879        If $iEnd < 1 Or $iEnd > $iUBound Then $iEnd = $iUBound
880        If $iStart < 0 Then $iStart = 0
881        If $iStart > $iEnd Then Return SetError(2, 0, -1)
882        Local $iMinIndex = $iStart
883        ; Search
884        If $iCompNumeric Then
885                For $i = $iStart To $iEnd
886                        If Number($avArray[$iMinIndex]) > Number($avArray[$i]) Then $iMinIndex = $i
887                Next
888        Else
889                For $i = $iStart To $iEnd
890                        If $avArray[$iMinIndex] > $avArray[$i] Then $iMinIndex = $i
891                Next
892        EndIf
893        Return $iMinIndex
894EndFunc   ;==>_ArrayMinIndex
895; #FUNCTION# ====================================================================================================================
896; Name...........: _ArrayMinIndex2D
897; Description ...: Returns the index where the lowest value occurs in the array.
898; Syntax.........: _ArrayMinIndex2D(Const ByRef $avArray[, $iCompNumeric = 0[, $iStart = 0[, $iEnd = 0[, $iSubItem = 0]]]])
899; Parameters ....: $avArray      - Array to search
900;                  $iCompNumeric - [optional] Comparison method:
901;                  |0 - compare alphanumerically
902;                  |1 - compare numerically
903;                  $iStart       - [optional] Index of array to start searching at
904;                  $iEnd         - [optional] Index of array to stop searching at
905;                  $iSubItem     - [optional] Subitem to search
906; Return values .: Success - The index of the minimum value in the array
907;                  Failure - -1, sets @error to:
908;                  |1 - $avArray is not an array
909;                  |2 - $iStart is greater than $iEnd
910;                  |3 - $avArray is not a 2 dimensional array
911; Author ........: Cephas <cephas at clergy dot net>
912; Modified.......: Jos van der Zande <jdeb at autoitscript dot com> - Added $iCompNumeric and $iStart parameters and logic, Ultima - added $iEnd parameter, code cleanup, optimization
913; Modified.......: BrewManNH - Added 2D array support
914; Remarks .......: This a modified version of _ArrayMinIndex which adds support for 2D arrays.
915; Related .......: _ArrayMax2D, _ArrayMaxIndex, _ArrayMin2D
916; Link ..........:
917; Example .......: Yes
918; ===============================================================================================================================
919Func _ArrayMinIndex2D(Const ByRef $avArray, $iCompNumeric = 0, $iStart = 0, $iEnd = 0, $iSubItem = 0)
920        If Not IsArray($avArray) Then Return SetError(1, 0, -1)
921        If UBound($avArray, 0) <> 2 Then Return SetError(3, 0, -1)
922        Local $iUBound = UBound($avArray) - 1
923        ; Bounds checking
924        If $iEnd < 1 Or $iEnd > $iUBound Then $iEnd = $iUBound
925        If $iSubItem > UBound($avArray, 2) - 1 Then $iSubItem = UBound($avArray, 2) - 1
926        If $iSubItem < 1 Then $iSubItem = 0
927        If $iStart < 0 Then $iStart = 0
928        If $iStart > $iEnd Then Return SetError(2, 0, -1)
929        Local $iMinIndex = $iStart
930        ; Search
931        If $iCompNumeric Then
932                For $i = $iStart To $iEnd
933                        If Number($avArray[$iMinIndex][$iSubItem]) > Number($avArray[$i][$iSubItem]) Then $iMinIndex = $i
934                Next
935        Else
936                For $i = $iStart To $iEnd
937                        If $avArray[$iMinIndex][$iSubItem] > $avArray[$i][$iSubItem] Then $iMinIndex = $i
938                Next
939        EndIf
940        Return $iMinIndex
941EndFunc   ;==>_ArrayMinIndex2D
942; #FUNCTION# ====================================================================================================================
943; Name...........: _ArrayPermute
944; Description ...: Returns an Array of the Permutations of all Elements in an Array
945; Syntax.........: _ArrayPermute(ByRef $avArray[, $sDelim = ""])
946; Parameters ....: $avArray - The Array to get Permutations
947;                  $sDelim - [optional] String result separator, default is "" for none
948; Return values .: Success - Returns an Array of Permutations
949;                  |$array[0] contains the number of strings returned.
950;                  |The remaining elements ($array[1], $array[2] ... $array[n]) contain the Permutations.
951;                  |Failure - Returns 0 and Sets @error:
952;                  |1 - The Input Must be an Array
953;                  |2 - $avArray is not a 1 dimensional array
954; Author ........: Erik Pilsits
955; Modified.......: 07/08/2008
956; Remarks .......: The input array must be 0-based, i.e. no counter in $array[0].  Based on the algorithm by Alexander Bogomolny.
957;+
958;                  http://www.bearcave.com/random_hacks/permute.html
959; Related .......: _ArrayCombinations
960; Link ..........:
961; Example .......: Yes
962; ===============================================================================================================================
963Func _ArrayPermute(ByRef $avArray, $sDelim = "")
964        If Not IsArray($avArray) Then Return SetError(1, 0, 0)
965        If UBound($avArray, 0) <> 1 Then Return SetError(2, 0, 0)
966        Local $iSize = UBound($avArray), $iFactorial = 1, $aIdx[$iSize], $aResult[1], $iCount = 1
967        For $i = 0 To $iSize - 1
968                $aIdx[$i] = $i
969        Next
970        For $i = $iSize To 1 Step -1
971                $iFactorial *= $i
972        Next
973        ReDim $aResult[$iFactorial + 1]
974        $aResult[0] = $iFactorial
975        __Array_ExeterInternal($avArray, 0, $iSize, $sDelim, $aIdx, $aResult, $iCount)
976        Return $aResult
977EndFunc   ;==>_ArrayPermute
978; #FUNCTION# ====================================================================================================================
979; Name...........: _ArrayPop
980; Description ...: Returns the last element of an array, deleting that element from the array at the same time.
981; Syntax.........: _ArrayPop(ByRef $avArray[, $cDelim = "|"])
982; Parameters ....: $avArray - Array to modify
983;                  $cDelim - [optional] For 2D arrays, the delimiter to insert between elements in the returned string.
984; Return values .: Success - The last element of the array, or for 2D arrays, the last "row" of the array in a delimited string
985;                  Failure - "", sets @error
986;                  |1 - The Input Must be an Array
987;                  |2 - $avArray is not a 1 or 2 dimensional array
988; Author ........: Cephas <cephas at clergy dot net>
989; Modified.......: Ultima - code cleanup
990; Modified.......: BrewManNH - Added 2D array support
991; Remarks .......: If the array has one element left, it will be set to "" after _ArrayPop() is used on it.
992; Related .......: _ArrayAdd, _ArrayDelete, _ArrayInsert, _ArrayPush
993; Link ..........:
994; Example .......: Yes
995; ===============================================================================================================================
996Func _ArrayPop(ByRef $avArray, $cDelim = "|")
997        If (Not IsArray($avArray)) Then Return SetError(1, 0, "")
998        If UBound($avArray, 0) > 2 Then Return SetError(2, 0, "")
999        If UBound($avArray, 0) = 1 Then
1000                Local $iUBound = UBound($avArray) - 1, $sLastVal = $avArray[$iUBound]
1001                ; Remove last item
1002                If Not $iUBound Then
1003                        $avArray = ""
1004                Else
1005                        ReDim $avArray[$iUBound]
1006                EndIf
1007                ; Return last item
1008                Return $sLastVal
1009        Else
1010                Local $iUBound = UBound($avArray) - 1, $iSubItems = UBound($avArray, 2)
1011                Local $sLastVal
1012                $sLastVal = $avArray[$iUBound][0] & $cDelim
1013                For $j = 1 To $iSubItems - 1
1014                        $sLastVal &= $avArray[$iUBound][$j] & $cDelim
1015                Next
1016                ; Remove last item
1017                If Not $iUBound Then
1018                        $avArray = ""
1019                Else
1020                        ReDim $avArray[$iUBound][$iSubItems]
1021                EndIf
1022                ; Return last item
1023                Return StringTrimRight($sLastVal, StringLen($cDelim))
1024        EndIf
1025EndFunc   ;==>_ArrayPop
1026; #FUNCTION# ====================================================================================================================
1027; Name...........: _ArrayPush
1028; Description ...: Add new values without increasing array size by inserting at the end the new value and deleting the first one or vice versa.
1029; Syntax.........: _ArrayPush(ByRef $avArray, $vValue[, $iDirection = 0])
1030; Parameters ....: $avArray    - Array to modify
1031;                  $vValue     - Value(s) to add (can be in an array)
1032;                  $iDirection - [optional] Direction to push existing array elements:
1033;                  |0 = Slide left (adding at the end)
1034;                  |1 = Slide right (adding at the start)
1035; Return values .: Success - 1
1036;                  Failure - 0, sets @error:
1037;                  |1 - $avArray is not an array
1038;                  |2 - $vValue is an array larger than $avArray (so it can't fit)
1039;                  |3 - $avArray is not a 1 dimensional array
1040; Author ........: Helias Gerassimou(hgeras), Ultima - code cleanup/rewrite (major optimization), fixed support for $vValue as an array
1041; Modified.......:
1042; Remarks .......: This function is used for continuous updates of data in array, where in other cases a vast size of array would be created.
1043;                  It keeps all values inside the array (something like History), minus the first one or the last one depending on direction chosen.
1044;                  It is similar to the push command in assembly.
1045; Related .......: _ArrayAdd, _ArrayConcatenate, _ArrayDelete, _ArrayInsert, _ArrayPop
1046; Link ..........:
1047; Example .......: Yes
1048; ===============================================================================================================================
1049Func _ArrayPush(ByRef $avArray, $vValue, $iDirection = 0)
1050        If (Not IsArray($avArray)) Then Return SetError(1, 0, 0)
1051        If UBound($avArray, 0) <> 1 Then Return SetError(3, 0, 0)
1052        Local $iUBound = UBound($avArray) - 1
1053        If IsArray($vValue) Then ; $vValue is an array
1054                Local $iUBoundS = UBound($vValue)
1055                If ($iUBoundS - 1) > $iUBound Then Return SetError(2, 0, 0)
1056                ; $vValue is an array smaller than $avArray
1057                If $iDirection Then ; slide right, add to front
1058                        For $i = $iUBound To $iUBoundS Step -1
1059                                $avArray[$i] = $avArray[$i - $iUBoundS]
1060                        Next
1061                        For $i = 0 To $iUBoundS - 1
1062                                $avArray[$i] = $vValue[$i]
1063                        Next
1064                Else ; slide left, add to end
1065                        For $i = 0 To $iUBound - $iUBoundS
1066                                $avArray[$i] = $avArray[$i + $iUBoundS]
1067                        Next
1068                        For $i = 0 To $iUBoundS - 1
1069                                $avArray[$i + $iUBound - $iUBoundS + 1] = $vValue[$i]
1070                        Next
1071                EndIf
1072        Else
1073                If $iDirection Then ; slide right, add to front
1074                        For $i = $iUBound To 1 Step -1
1075                                $avArray[$i] = $avArray[$i - 1]
1076                        Next
1077                        $avArray[0] = $vValue
1078                Else ; slide left, add to end
1079                        For $i = 0 To $iUBound - 1
1080                                $avArray[$i] = $avArray[$i + 1]
1081                        Next
1082                        $avArray[$iUBound] = $vValue
1083                EndIf
1084        EndIf
1085        Return 1
1086EndFunc   ;==>_ArrayPush
1087; #FUNCTION# ====================================================================================================================
1088; Name...........: _ArrayReverse
1089; Description ...: Takes the given array and reverses the order in which the elements appear in the array.
1090; Syntax.........: _ArrayReverse(ByRef $avArray[, $iStart = 0[, $iEnd = 0]])
1091; Parameters ....: $avArray - Array to modify
1092;                  $iStart  - [optional] Index of array to start modifying at
1093;                  $iEnd    - [optional] Index of array to stop modifying at
1094; Return values .: Success - 1
1095;                  Failure - 0, sets @error:
1096;                  |1 - $avArray is not an array
1097;                  |2 - $iStart is greater than $iEnd
1098;                  |3 - $avArray is not a 1 or 2 dimensional array
1099; Author ........: Brian Keene
1100; Modified.......: Jos van der Zande <jdeb at autoitscript dot com> -  added $iStart parameter and logic, Tylo - added $iEnd parameter and rewrote it for speed, Ultima - code cleanup, minor optimization
1101; Modified.......: BrewManNH - Added 2D array support
1102; Remarks .......:
1103; Related .......: _ArraySwap
1104; Link ..........:
1105; Example .......: Yes
1106; ===============================================================================================================================
1107Func _ArrayReverse(ByRef $avArray, $iStart = 0, $iEnd = 0)
1108        If Not IsArray($avArray) Then Return SetError(1, 0, 0)
1109        If UBound($avArray, 0) > 2 Then Return SetError(3, 0, 0)
1110        Local $vTmp, $iUBound = UBound($avArray) - 1
1111        ; Bounds checking
1112        If $iEnd < 1 Or $iEnd > $iUBound Then $iEnd = $iUBound
1113        If $iStart < 0 Then $iStart = 0
1114        If $iStart > $iEnd Then Return SetError(2, 0, 0)
1115        If UBound($avArray, 0) = 1 Then
1116                ; Reverse
1117                For $i = $iStart To Int(($iStart + $iEnd - 1) / 2)
1118                        $vTmp = $avArray[$i]
1119                        $avArray[$i] = $avArray[$iEnd]
1120                        $avArray[$iEnd] = $vTmp
1121                        $iEnd -= 1
1122                Next
1123                Return 1
1124        Else
1125                ; Reverse
1126                For $i = $iStart To Int(($iStart + $iEnd - 1) / 2)
1127                        For $j = 0 To UBound($avArray, 2) - 1
1128                                $vTmp = $avArray[$i][$j]
1129                                $avArray[$i][$j] = $avArray[$iEnd][$j]
1130                                $avArray[$iEnd][$j] = $vTmp
1131                        Next
1132                        $iEnd -= 1
1133                Next
1134                Return 1
1135        EndIf
1136EndFunc   ;==>_ArrayReverse
1137; #FUNCTION# ====================================================================================================================
1138; Name...........: _ArraySearch
1139; Description ...: Finds an entry within a 1D or 2D array. Similar to _ArrayBinarySearch(), except that the array does not need to be sorted.
1140; Syntax.........: _ArraySearch(Const ByRef $avArray, $vValue[, $iStart = 0[, $iEnd = 0[, $iCase = 0[, $iPartial = 0[, $iForward = 1[, $iSubItem = -1]]]]]])
1141; Parameters ....: $avArray  - The array to search
1142;                  $vValue   - What to search $avArray for
1143;                  $iStart   - [optional] Index of array to start searching at
1144;                  $iEnd     - [optional] Index of array to stop searching at
1145;                  $iCase    - [optional] If set to 1, search is case sensitive
1146;                  $iPartial - [optional] If set to 1, executes a partial search
1147;                  $iForward - [optional] If set to 0, searches the array from end to beginning (instead of beginning to end)
1148;                  $iSubItem - [optional] Sub-index to search on in 2D arrays
1149; Return values .: Success - The index that $vValue was found at
1150;                  Failure - -1, sets @error:
1151;                  |1 - $avArray is not an array
1152;                  |2 - $avArray is not a 1 or 2 dimensional array
1153;                  |4 - $iStart is greater than $iEnd
1154;                  |6 - $vValue was not found in array
1155;                  |7 - $avArray has too many dimensions
1156;                  |(3, 5 - Deprecated error codes)
1157; Author ........: SolidSnake <MetalGX91 at GMail dot com>
1158; Modified.......: gcriaco <gcriaco at gmail dot com>, Ultima - 2D arrays supported, directional search, code cleanup, optimization
1159; Remarks .......: This function might be slower than _ArrayBinarySearch() but is useful when the array's order can't be altered.
1160; Related .......: _ArrayBinarySearch, _ArrayFindAll
1161; Link ..........:
1162; Example .......: Yes
1163; ===============================================================================================================================
1164Func _ArraySearch(Const ByRef $avArray, $vValue, $iStart = 0, $iEnd = 0, $iCase = 0, $iPartial = 0, $iForward = 1, $iSubItem = -1)
1165        If Not IsArray($avArray) Then Return SetError(1, 0, -1)
1166        If UBound($avArray, 0) > 2 Or UBound($avArray, 0) < 1 Then Return SetError(2, 0, -1)
1167        Local $iUBound = UBound($avArray) - 1
1168        ; Bounds checking
1169        If $iEnd < 1 Or $iEnd > $iUBound Then $iEnd = $iUBound
1170        If $iStart < 0 Then $iStart = 0
1171        If $iStart > $iEnd Then Return SetError(4, 0, -1)
1172        ; Direction (flip if $iForward = 0)
1173        Local $iStep = 1
1174        If Not $iForward Then
1175                Local $iTmp = $iStart
1176                $iStart = $iEnd
1177                $iEnd = $iTmp
1178                $iStep = -1
1179        EndIf
1180        ; Search
1181        Switch UBound($avArray, 0)
1182                Case 1 ; 1D array search
1183                        If Not $iPartial Then
1184                                If Not $iCase Then
1185                                        For $i = $iStart To $iEnd Step $iStep
1186                                                If $avArray[$i] = $vValue Then Return $i
1187                                        Next
1188                                Else
1189                                        For $i = $iStart To $iEnd Step $iStep
1190                                                If $avArray[$i] == $vValue Then Return $i
1191                                        Next
1192                                EndIf
1193                        Else
1194                                For $i = $iStart To $iEnd Step $iStep
1195                                        If StringInStr($avArray[$i], $vValue, $iCase) > 0 Then Return $i
1196                                Next
1197                        EndIf
1198                Case 2 ; 2D array search
1199                        Local $iUBoundSub = UBound($avArray, 2) - 1
1200                        If $iSubItem > $iUBoundSub Then $iSubItem = $iUBoundSub
1201                        If $iSubItem < 0 Then
1202                                ; will search for all Col
1203                                $iSubItem = 0
1204                        Else
1205                                $iUBoundSub = $iSubItem
1206                        EndIf
1207                        For $j = $iSubItem To $iUBoundSub
1208                                If Not $iPartial Then
1209                                        If Not $iCase Then
1210                                                For $i = $iStart To $iEnd Step $iStep
1211                                                        If $avArray[$i][$j] = $vValue Then Return $i
1212                                                Next
1213                                        Else
1214                                                For $i = $iStart To $iEnd Step $iStep
1215                                                        If $avArray[$i][$j] == $vValue Then Return $i
1216                                                Next
1217                                        EndIf
1218                                Else
1219                                        For $i = $iStart To $iEnd Step $iStep
1220                                                If StringInStr($avArray[$i][$j], $vValue, $iCase) > 0 Then Return $i
1221                                        Next
1222                                EndIf
1223                        Next
1224                Case Else
1225                        Return SetError(7, 0, -1)
1226        EndSwitch
1227        Return SetError(6, 0, -1)
1228EndFunc   ;==>_ArraySearch
1229; #FUNCTION# ====================================================================================================================
1230; Name...........: _ArraySort
1231; Description ...: Sort a 1D or 2D array on a specific index using the quicksort/insertionsort algorithms.
1232; Syntax.........: _ArraySort(ByRef $avArray[, $iDescending = 0[, $iStart = 0[, $iEnd = 0[, $iSubItem = 0]]]])
1233; Parameters ....: $avArray     - Array to sort
1234;                  $iDescending - [optional] If set to 1, sort descendingly
1235;                  $iStart      - [optional] Index of array to start sorting at
1236;                  $iEnd        - [optional] Index of array to stop sorting at
1237;                  $iSubItem    - [optional] Sub-index to sort on in 2D arrays
1238; Return values .: Success - 1
1239;                  Failure - 0, sets @error:
1240;                  |1 - $avArray is not an array
1241;                  |2 - $iStart is greater than $iEnd
1242;                  |3 - $iSubItem is greater than subitem count
1243;                  |4 - $avArray has too many dimensions
1244; Author ........: Jos van der Zande <jdeb at autoitscript dot com>
1245; Modified.......: LazyCoder - added $iSubItem option, Tylo - implemented stable QuickSort algo, Jos van der Zande - changed logic to correctly Sort arrays with mixed Values and Strings, Ultima - major optimization, code cleanup, removed $i_Dim parameter
1246; Remarks .......:
1247; Related .......:
1248; Link ..........:
1249; Example .......: Yes
1250; ===============================================================================================================================
1251Func _ArraySort(ByRef $avArray, $iDescending = 0, $iStart = 0, $iEnd = 0, $iSubItem = 0)
1252        If Not IsArray($avArray) Then Return SetError(1, 0, 0)
1253        Local $iUBound = UBound($avArray) - 1
1254        ; Bounds checking
1255        If $iEnd < 1 Or $iEnd > $iUBound Then $iEnd = $iUBound
1256        If $iStart < 0 Then $iStart = 0
1257        If $iStart > $iEnd Then Return SetError(2, 0, 0)
1258        ; Sort
1259        Switch UBound($avArray, 0)
1260                Case 1
1261                        __ArrayQuickSort1D($avArray, $iStart, $iEnd)
1262                        If $iDescending Then _ArrayReverse($avArray, $iStart, $iEnd)
1263                Case 2
1264                        Local $iSubMax = UBound($avArray, 2) - 1
1265                        If $iSubItem > $iSubMax Then Return SetError(3, 0, 0)
1266                        If $iDescending Then
1267                                $iDescending = -1
1268                        Else
1269                                $iDescending = 1
1270                        EndIf
1271                        __ArrayQuickSort2D($avArray, $iDescending, $iStart, $iEnd, $iSubItem, $iSubMax)
1272                Case Else
1273                        Return SetError(4, 0, 0)
1274        EndSwitch
1275        Return 1
1276EndFunc   ;==>_ArraySort
1277; #FUNCTION# ====================================================================================================================
1278; Name...........: _ArraySwap
1279; Description ...: Swaps two items.
1280; Syntax.........: _ArraySwap(ByRef $vItem1, ByRef $vItem2)
1281; Parameters ....: $vItem1 - First item to swap
1282;                  $vItem2 - Second item to swap
1283; Return values .: None.
1284; Author ........: David Nuttall <danuttall at rocketmail dot com>
1285; Modified.......: Ultima - minor optimization
1286; Remarks .......: This function swaps the two items in place, since they're passed by reference. Regular, non-array variables can also be swapped by this function.
1287; Related .......: _ArrayReverse
1288; Link ..........:
1289; Example .......: Yes
1290; ===============================================================================================================================
1291Func _ArraySwap(ByRef $vItem1, ByRef $vItem2)
1292        Local $vTmp = $vItem1
1293        $vItem1 = $vItem2
1294        $vItem2 = $vTmp
1295EndFunc   ;==>_ArraySwap
1296; #FUNCTION# ====================================================================================================================
1297; Name...........: _ArrayToClip
1298; Description ...: Sends the contents of an array to the clipboard, each element delimited by a carriage return.
1299; Syntax.........: _ArrayToClip(Const ByRef $avArray[, $iStart = 0[, $iEnd = 0[, $iSubItem = 0]]])
1300; Parameters ....: $avArray - Array to copy to clipboard
1301;                  $iStart  - [optional] Index of array to start copying at
1302;                  $iEnd    - [optional] Index of array to stop copying at
1303;                  $iSubItem- [optional] Dimension of array to copy
1304; Return values .: Success - 1
1305;                  Failure - 0, sets @error:
1306;                  |-1 - ClipPut() failed
1307;                  |Other - See _ArrayToString() description for error codes
1308; Author ........: Cephas <cephas at clergy dot net>
1309; Modified.......: Jos van der Zande <jdeb at autoitscript dot com> - added $iStart parameter and logic, Ultima - added $iEnd parameter, make use of _ArrayToString() instead of duplicating efforts
1310; Remarks .......:
1311; Related .......: _ArrayToString
1312; Link ..........:
1313; Example .......: Yes
1314; ===============================================================================================================================
1315Func _ArrayToClip(Const ByRef $avArray, $iStart = 0, $iEnd = 0, $iSubItem = 0)
1316        If UBound($avArray, 0) = 1 Then
1317                Local $sResult = _ArrayToString($avArray, @CR, $iStart, $iEnd)
1318                If @error Then Return SetError(@error, 0, 0)
1319                Return ClipPut($sResult)
1320        Else
1321                If $iSubItem > UBound($avArray, 2) - 1 Then $iSubItem = UBound($avArray, 2) - 1
1322                If $iSubItem < 1 Then $iSubItem = 0
1323                Local $sResult = _ArrayToString($avArray, @CR, $iStart, $iEnd, $iSubItem)
1324                If @error Then Return SetError(@error, 0, 0)
1325                Return ClipPut($sResult)
1326        EndIf
1327EndFunc   ;==>_ArrayToClip
1328; #FUNCTION# ====================================================================================================================
1329; Name...........: _ArrayToString
1330; Description ...: Places the elements of an array into a single string, separated by the specified delimiter.
1331; Syntax.........: _ArrayToString(Const ByRef $avArray[, $sDelim = "|"[, $iStart = 0[, $iEnd = 0]]])
1332; Parameters ....: $avArray - Array to combine
1333;                  $sDelim  - [optional] Delimiter for combined string
1334;                  $iStart  - [optional] Index of array to start combining at
1335;                  $iEnd    - [optional] Index of array to stop combining at
1336;                  $iSubItem- [optional] Subitem to copy
1337; Return values .: Success - string which combined selected elements separated by the delimiter string.
1338;                  Failure - "", sets @error:
1339;                  |1 - $avArray is not an array
1340;                  |2 - $iStart is greater than $iEnd
1341;                  |3 - $avArray is not an 1 or 2 dimensional array
1342; Author ........: Brian Keene <brian_keene at yahoo dot com>, Valik - rewritten
1343; Modified.......: Ultima - code cleanup
1344; Modified.......: BrewManNH - Added 2D array support
1345; Remarks .......:
1346; Related .......: StringSplit, _ArrayToClip
1347; Link ..........:
1348; Example .......: Yes
1349; ===============================================================================================================================
1350Func _ArrayToString(Const ByRef $avArray, $sDelim = "|", $iStart = 0, $iEnd = 0, $iSubItem = 0)
1351        If Not IsArray($avArray) Then Return SetError(1, 0, "")
1352        If UBound($avArray, 0) > 2 Then Return SetError(3, 0, "")
1353        Local $sResult, $iUBound = UBound($avArray) - 1
1354        ; Bounds checking
1355        If $iEnd < 1 Or $iEnd > $iUBound Then $iEnd = $iUBound
1356        If $iStart < 0 Then $iStart = 0
1357        If $iStart > $iEnd Then Return SetError(2, 0, "")
1358        If UBound($avArray, 0) = 1 Then
1359                ; Combine
1360                For $i = $iStart To $iEnd
1361                        $sResult &= $avArray[$i] & $sDelim
1362                Next
1363                Return StringTrimRight($sResult, StringLen($sDelim))
1364        Else
1365                If $iSubItem > UBound($avArray, 2) - 1 Then $iSubItem = UBound($avArray, 2) - 1
1366                If $iSubItem < 1 Then $iSubItem = 0
1367                ; Combine
1368                For $i = $iStart To $iEnd
1369                        $sResult &= $avArray[$i][$iSubItem] & $sDelim
1370                Next
1371                Return StringTrimRight($sResult, StringLen($sDelim))
1372        EndIf
1373EndFunc   ;==>_ArrayToString
1374; #FUNCTION# ====================================================================================================================
1375; Name...........: _ArrayTrim
1376; Description ...: Trims a certain number of characters from all elements in an array.
1377; Syntax.........: _ArrayTrim(ByRef $avArray, $iTrimNum[, $iDirection = 0[, $iStart = 0[, $iEnd = 0]]])
1378; Parameters ....: $avArray    - Array to modify
1379;                  $iTrimNum   - Number of characters to remove
1380;                  $iDirection - [optional] Direction to trim:
1381;                  |0 - trim left
1382;                  |1 - trim right
1383;                  $iStart     - [optional] Index of array to start trimming at
1384;                  $iEnd       - [optional] Index of array to stop trimming at
1385; Return values .: Success - 1
1386;                  Failure - 0, sets @error:
1387;                  |1 - $avArray is not an array
1388;                  |2 - $avArray is not an 1 or 2 dimensional array
1389;                  |5 - $iStart is greater than $iEnd
1390;                  |(3-4 - Deprecated error codes)
1391; Author ........: Adam Moore (redndahead)
1392; Modified.......: Ultima - code cleanup, optimization
1393; Remarks .......:
1394; Related .......:
1395; Link ..........:
1396; Example .......: Yes
1397; ===============================================================================================================================
1398Func _ArrayTrim(ByRef $avArray, $iTrimNum, $iDirection = 0, $iStart = 0, $iEnd = 0)
1399        If Not IsArray($avArray) Then Return SetError(1, 0, 0)
1400        If UBound($avArray, 0) > 2 Then Return SetError(2, 0, 0)
1401        Local $iUBound = UBound($avArray) - 1
1402        ; Bounds checking
1403        If $iEnd < 1 Or $iEnd > $iUBound Then $iEnd = $iUBound
1404        If $iStart < 0 Then $iStart = 0
1405        If $iStart > $iEnd Then Return SetError(5, 0, 0)
1406        If UBound($avArray, 0) = 1 Then
1407                ; Trim
1408                If $iDirection Then
1409                        For $i = $iStart To $iEnd
1410                                $avArray[$i] = StringTrimRight($avArray[$i], $iTrimNum)
1411                        Next
1412                Else
1413                        For $i = $iStart To $iEnd
1414                                $avArray[$i] = StringTrimLeft($avArray[$i], $iTrimNum)
1415                        Next
1416                EndIf
1417                Return 1
1418        Else
1419                ; Trim
1420                If $iDirection Then
1421                        For $i = $iStart To $iEnd
1422                                For $j = 0 To UBound($avArray, 2) - 1
1423                                        $avArray[$i][$j] = StringTrimRight($avArray[$i][$j], $iTrimNum)
1424                                Next
1425                        Next
1426                Else
1427                        For $i = $iStart To $iEnd
1428                                For $j = 0 To UBound($avArray, 2) - 1
1429                                        $avArray[$i][$j] = StringTrimLeft($avArray[$i][$j], $iTrimNum)
1430                                Next
1431                        Next
1432                EndIf
1433                Return 1
1434        EndIf
1435EndFunc   ;==>_ArrayTrim
1436; #FUNCTION# ====================================================================================================================
1437; Name...........: _ArrayUnique
1438; Description ...: Returns the Elements of a 1 or 2-dimensional array deleting all duplicate items
1439; Syntax.........: _ArrayUnique($aArray[, $iDimension = 1[, $iBase = 0[, $iCase = 0[, $vDelim = "|"]]]])
1440; Parameters ....: $aArray - The Array to use
1441;                  $iDimension  - [optional] The Dimension of the Array to use
1442;                  $iBase  - [optional] Is the Array 0-base or 1-base index.  0-base by default
1443;                  $iCase  - [optional] Flag to indicate if the operations should be case sensitive.
1444;                  0 = not case sensitive, using the user's locale (default)
1445;                  1 = case sensitive
1446;                  2 = not case sensitive, using a basic/faster comparison
1447;                  $vDelim  - [optional] One or more characters to use as delimiters.  However, cannot forsee its usefullness
1448; Return values .: Success - Returns a 1-dimensional array containing only the unique elements of that Dimension
1449;                  Failure - Returns 0 and Sets @Error:
1450;                  0 - No error.
1451;                  1 - Returns 0 if parameter is not an array.
1452;                  2 - _ArrayUnique failed for some other reason
1453;                  3 - Array dimension is invalid, should be an integer greater than 0
1454; Author ........: SmOke_N
1455; Modified.......: litlmike
1456; Remarks .......: Returns an array, the first element ($array[0]) contains the number of strings returned, the remaining elements ($array[1], $array[2], etc.) contain the unique strings.
1457; Related .......: _ArrayMax, _ArrayMin
1458; Link ..........:
1459; Example .......: Yes
1460; ===============================================================================================================================
1461Func _ArrayUnique($aArray, $iDimension = 1, $iBase = 0, $iCase = 0, $vDelim = "|")
1462        Local $iUboundDim
1463        ;$aArray used to be ByRef, but litlmike altered it to allow for the choosing of 1 Array Dimension, without altering the original array
1464        If $vDelim = "|" Then $vDelim = Chr(01) ; by SmOke_N, modified by litlmike
1465        If Not IsArray($aArray) Then Return SetError(1, 0, 0) ;Check to see if it is valid array
1466        ;Checks that the given Dimension is Valid
1467        If Not $iDimension > 0 Then
1468                Return SetError(3, 0, 0) ;Check to see if it is valid array dimension, Should be greater than 0
1469        Else
1470                ;If Dimension Exists, then get the number of "Rows"
1471                $iUboundDim = UBound($aArray, 1) ;Get Number of "Rows"
1472                If @error Then Return SetError(3, 0, 0) ;2 = Array dimension is invalid.
1473                ;If $iDimension Exists, And the number of "Rows" is Valid:
1474                If $iDimension > 1 Then ;Makes sure the Array dimension desired is more than 1-dimensional
1475                        Local $aArrayTmp[1] ;Declare blank array, which will hold the dimension declared by user
1476                        For $i = 0 To $iUboundDim - 1 ;Loop through "Rows"
1477                                _ArrayAdd($aArrayTmp, $aArray[$i][$iDimension - 1]) ;$iDimension-1 to match Dimension
1478                        Next
1479                        _ArrayDelete($aArrayTmp, 0) ;Get rid of 1st-element which is blank
1480                Else ;Makes sure the Array dimension desired is 1-dimensional
1481                        ;If Dimension Exists, And the number of "Rows" is Valid, and the Dimension desired is not > 1, then:
1482                        ;For the Case that the array is 1-Dimensional
1483                        If UBound($aArray, 0) = 1 Then ;Makes sure the Array is only 1-Dimensional
1484                                Dim $aArrayTmp[1] ;Declare blank array, which will hold the dimension declared by user
1485                                For $i = 0 To $iUboundDim - 1
1486                                        _ArrayAdd($aArrayTmp, $aArray[$i])
1487                                Next
1488                                _ArrayDelete($aArrayTmp, 0) ;Get rid of 1st-element which is blank
1489                        Else ;For the Case that the array is 2-Dimensional
1490                                Dim $aArrayTmp[1] ;Declare blank array, which will hold the dimension declared by user
1491                                For $i = 0 To $iUboundDim - 1
1492                                        _ArrayAdd($aArrayTmp, $aArray[$i][$iDimension - 1]) ;$iDimension-1 to match Dimension
1493                                Next
1494                                _ArrayDelete($aArrayTmp, 0) ;Get rid of 1st-element which is blank
1495                        EndIf
1496                EndIf
1497        EndIf
1498        Local $sHold ;String that holds the Unique array info
1499        For $iCC = $iBase To UBound($aArrayTmp) - 1 ;Loop Through array
1500                ;If Not the case that the element is already in $sHold, then add it
1501                If Not StringInStr($vDelim & $sHold, $vDelim & $aArrayTmp[$iCC] & $vDelim, $iCase) Then _
1502                                $sHold &= $aArrayTmp[$iCC] & $vDelim
1503        Next
1504        If $sHold Then
1505                $aArrayTmp = StringSplit(StringTrimRight($sHold, StringLen($vDelim)), $vDelim, 1) ;Split the string into an array
1506                Return $aArrayTmp ;SmOke_N's version used to Return SetError(0, 0, 0)
1507        EndIf
1508        Return SetError(2, 0, 0) ;If the script gets this far, it has failed
1509EndFunc   ;==>_ArrayUnique
1510; #INTERNAL_USE_ONLY# ===========================================================================================================
1511; Name...........: __Array_Combinations
1512; Description ...: Creates Combination
1513; Syntax.........: __Array_Combinations($iN, $iR)
1514; Parameters ....: $iN - Value passed on from UBound($avArray)
1515;                  $iR - Size of the combinations set
1516; Return values .: Integer value of the number of combinations
1517; Author ........: Erik Pilsits
1518; Modified.......: 07/08/2008
1519; Remarks .......: This function is used internally. PBased on an algorithm by Kenneth H. Rosen.
1520;+
1521;                   http://www.bearcave.com/random_hacks/permute.html
1522; Related .......:
1523; Link ..........:
1524; Example .......:
1525; ===============================================================================================================================
1526Func __Array_Combinations($iN, $iR)
1527        Local $i_Total = 1
1528        For $i = $iR To 1 Step -1
1529                $i_Total *= ($iN / $i)
1530                $iN -= 1
1531        Next
1532        Return Round($i_Total)
1533EndFunc   ;==>__Array_Combinations
1534; #INTERNAL_USE_ONLY# ===========================================================================================================
1535; Name...........: __Array_ExeterInternal
1536; Description ...: Permute Function based on an algorithm from Exeter University.
1537; Syntax.........: __Array_ExeterInternal(ByRef $avArray, $iStart, $iSize, $sDelim, ByRef $aIdx, ByRef $aResult)
1538; Parameters ....: $avArray - The Array to get Permutations
1539;                  $iStart - Starting Point for Loop
1540;                  $iSize - End Point for Loop
1541;                  $sDelim - String result separator
1542;                  $aIdx - Array Used in Rotations
1543;                  $aResult - Resulting Array
1544; Return values .: Success      - Computer name
1545; Author ........: Erik Pilsits
1546; Modified.......: 07/08/2008
1547; Remarks .......: This function is used internally. Permute Function based on an algorithm from Exeter University.
1548;+
1549;                   http://www.bearcave.com/random_hacks/permute.html
1550; Related .......:
1551; Link ..........:
1552; Example .......:
1553; ===============================================================================================================================
1554Func __Array_ExeterInternal(ByRef $avArray, $iStart, $iSize, $sDelim, ByRef $aIdx, ByRef $aResult, ByRef $iCount)
1555        If $iStart == $iSize - 1 Then
1556                For $i = 0 To $iSize - 1
1557                        $aResult[$iCount] &= $avArray[$aIdx[$i]] & $sDelim
1558                Next
1559                If $sDelim <> "" Then $aResult[$iCount] = StringTrimRight($aResult[$iCount], 1)
1560                $iCount += 1
1561        Else
1562                Local $iTemp
1563                For $i = $iStart To $iSize - 1
1564                        $iTemp = $aIdx[$i]
1565                        $aIdx[$i] = $aIdx[$iStart]
1566                        $aIdx[$iStart] = $iTemp
1567                        __Array_ExeterInternal($avArray, $iStart + 1, $iSize, $sDelim, $aIdx, $aResult, $iCount)
1568                        $aIdx[$iStart] = $aIdx[$i]
1569                        $aIdx[$i] = $iTemp
1570                Next
1571        EndIf
1572EndFunc   ;==>__Array_ExeterInternal
1573; #INTERNAL_USE_ONLY# ===========================================================================================================
1574; Name...........: __Array_GetNext
1575; Description ...: Creates Combination
1576; Syntax.........: __Array_GetNext($iN, $iR, ByRef $iLeft, $iTotal, ByRef $aIdx)
1577; Parameters ....: $iN - Value passed on from UBound($avArray)
1578;                  $iR - Size of the combinations set
1579;                  $iLeft - Remaining number of combinations
1580;                  $iTotal - Total number of combinations
1581;                  $aIdx - Array containing combinations
1582; Return values .: Function only changes values ByRef
1583; Author ........: Erik Pilsits
1584; Modified.......: 07/08/2008
1585; Remarks .......: This function is used internally. PBased on an algorithm by Kenneth H. Rosen.
1586;+
1587;                   http://www.bearcave.com/random_hacks/permute.html
1588; Related .......:
1589; Link ..........:
1590; Example .......:
1591; ===============================================================================================================================
1592Func __Array_GetNext($iN, $iR, ByRef $iLeft, $iTotal, ByRef $aIdx)
1593        If $iLeft == $iTotal Then
1594                $iLeft -= 1
1595                Return
1596        EndIf
1597        Local $i = $iR - 1
1598        While $aIdx[$i] == $iN - $iR + $i
1599                $i -= 1
1600        WEnd
1601        $aIdx[$i] += 1
1602        For $j = $i + 1 To $iR - 1
1603                $aIdx[$j] = $aIdx[$i] + $j - $i
1604        Next
1605        $iLeft -= 1
1606EndFunc   ;==>__Array_GetNext
1607; #INTERNAL_USE_ONLY# ===========================================================================================================
1608; Name...........: __ArrayQuickSort1D
1609; Description ...: Helper function for sorting 1D arrays
1610; Syntax.........: __ArrayQuickSort1D(ByRef $avArray, ByRef $iStart, ByRef $iEnd)
1611; Parameters ....: $avArray - Array to sort
1612;                  $iStart  - Index of array to start sorting at
1613;                  $iEnd    - Index of array to stop sorting at
1614; Return values .: None
1615; Author ........: Jos van der Zande, LazyCoder, Tylo, Ultima
1616; Modified.......:
1617; Remarks .......: For Internal Use Only
1618; Related .......:
1619; Link ..........:
1620; Example .......:
1621; ===============================================================================================================================
1622Func __ArrayQuickSort1D(ByRef $avArray, ByRef $iStart, ByRef $iEnd)
1623        If $iEnd <= $iStart Then Return
1624        Local $vTmp
1625        ; InsertionSort (faster for smaller segments)
1626        If ($iEnd - $iStart) < 15 Then
1627                Local $vCur
1628                For $i = $iStart + 1 To $iEnd
1629                        $vTmp = $avArray[$i]
1630                        If IsNumber($vTmp) Then
1631                                For $j = $i - 1 To $iStart Step -1
1632                                        $vCur = $avArray[$j]
1633                                        ; If $vTmp >= $vCur Then ExitLoop
1634                                        If ($vTmp >= $vCur And IsNumber($vCur)) Or (Not IsNumber($vCur) And StringCompare($vTmp, $vCur) >= 0) Then ExitLoop
1635                                        $avArray[$j + 1] = $vCur
1636                                Next
1637                        Else
1638                                For $j = $i - 1 To $iStart Step -1
1639                                        If (StringCompare($vTmp, $avArray[$j]) >= 0) Then ExitLoop
1640                                        $avArray[$j + 1] = $avArray[$j]
1641                                Next
1642                        EndIf
1643                        $avArray[$j + 1] = $vTmp
1644                Next
1645                Return
1646        EndIf
1647        ; QuickSort
1648        Local $L = $iStart, $R = $iEnd, $vPivot = $avArray[Int(($iStart + $iEnd) / 2)], $fNum = IsNumber($vPivot)
1649        Do
1650                If $fNum Then
1651                        ; While $avArray[$L] < $vPivot
1652                        While ($avArray[$L] < $vPivot And IsNumber($avArray[$L])) Or (Not IsNumber($avArray[$L]) And StringCompare($avArray[$L], $vPivot) < 0)
1653                                $L += 1
1654                        WEnd
1655                        ; While $avArray[$R] > $vPivot
1656                        While ($avArray[$R] > $vPivot And IsNumber($avArray[$R])) Or (Not IsNumber($avArray[$R]) And StringCompare($avArray[$R], $vPivot) > 0)
1657                                $R -= 1
1658                        WEnd
1659                Else
1660                        While (StringCompare($avArray[$L], $vPivot) < 0)
1661                                $L += 1
1662                        WEnd
1663                        While (StringCompare($avArray[$R], $vPivot) > 0)
1664                                $R -= 1
1665                        WEnd
1666                EndIf
1667                ; Swap
1668                If $L <= $R Then
1669                        $vTmp = $avArray[$L]
1670                        $avArray[$L] = $avArray[$R]
1671                        $avArray[$R] = $vTmp
1672                        $L += 1
1673                        $R -= 1
1674                EndIf
1675        Until $L > $R
1676        __ArrayQuickSort1D($avArray, $iStart, $R)
1677        __ArrayQuickSort1D($avArray, $L, $iEnd)
1678EndFunc   ;==>__ArrayQuickSort1D
1679; #INTERNAL_USE_ONLY# ===========================================================================================================
1680; Name...........: __ArrayQuickSort2D
1681; Description ...: Helper function for sorting 2D arrays
1682; Syntax.........: __ArrayQuickSort2D(ByRef $avArray, ByRef $iStep, ByRef $iStart, ByRef $iEnd, ByRef $iSubItem, ByRef $iSubMax)
1683; Parameters ....: $avArray  - Array to sort
1684;                  $iStep    - Step size (should be 1 to sort ascending, -1 to sort descending!)
1685;                  $iStart   - Index of array to start sorting at
1686;                  $iEnd     - Index of array to stop sorting at
1687;                  $iSubItem - Sub-index to sort on in 2D arrays
1688;                  $iSubMax  - Maximum sub-index that array has
1689; Return values .: None
1690; Author ........: Jos van der Zande, LazyCoder, Tylo, Ultima
1691; Modified.......:
1692; Remarks .......: For Internal Use Only
1693; Related .......:
1694; Link ..........:
1695; Example .......:
1696; ===============================================================================================================================
1697Func __ArrayQuickSort2D(ByRef $avArray, ByRef $iStep, ByRef $iStart, ByRef $iEnd, ByRef $iSubItem, ByRef $iSubMax)
1698        If $iEnd <= $iStart Then Return
1699        ; QuickSort
1700        Local $vTmp, $L = $iStart, $R = $iEnd, $vPivot = $avArray[Int(($iStart + $iEnd) / 2)][$iSubItem], $fNum = IsNumber($vPivot)
1701        Do
1702                If $fNum Then
1703                        ; While $avArray[$L][$iSubItem] < $vPivot
1704                        While ($iStep * ($avArray[$L][$iSubItem] - $vPivot) < 0 And IsNumber($avArray[$L][$iSubItem])) Or (Not IsNumber($avArray[$L][$iSubItem]) And $iStep * StringCompare($avArray[$L][$iSubItem], $vPivot) < 0)
1705                                $L += 1
1706                        WEnd
1707                        ; While $avArray[$R][$iSubItem] > $vPivot
1708                        While ($iStep * ($avArray[$R][$iSubItem] - $vPivot) > 0 And IsNumber($avArray[$R][$iSubItem])) Or (Not IsNumber($avArray[$R][$iSubItem]) And $iStep * StringCompare($avArray[$R][$iSubItem], $vPivot) > 0)
1709                                $R -= 1
1710                        WEnd
1711                Else
1712                        While ($iStep * StringCompare($avArray[$L][$iSubItem], $vPivot) < 0)
1713                                $L += 1
1714                        WEnd
1715                        While ($iStep * StringCompare($avArray[$R][$iSubItem], $vPivot) > 0)
1716                                $R -= 1
1717                        WEnd
1718                EndIf
1719                ; Swap
1720                If $L <= $R Then
1721                        For $i = 0 To $iSubMax
1722                                $vTmp = $avArray[$L][$i]
1723                                $avArray[$L][$i] = $avArray[$R][$i]
1724                                $avArray[$R][$i] = $vTmp
1725                        Next
1726                        $L += 1
1727                        $R -= 1
1728                EndIf
1729        Until $L > $R
1730        __ArrayQuickSort2D($avArray, $iStep, $iStart, $R, $iSubItem, $iSubMax)
1731        __ArrayQuickSort2D($avArray, $iStep, $L, $iEnd, $iSubItem, $iSubMax)
1732EndFunc   ;==>__ArrayQuickSort2D