#include-once #cs Author & bugs: jchd (forum) or jcd@antichoc.net -------------------------------------------------------------------------------------------------- All the functions in this UDF report errors as follows: return value: valid subarray or single value 0 if error (not an error indicator: use @error for that) @error 0 = no error 1 = error @extended 0 = no error 1 = first input parameter is not an array 2 = input array dimension(s) invalid for function invoked 3 = start index out of range 4 = requested output dimension out of range 5 = requested transpose dimension out of range -------------------------------------------------------------------------------------------------- Here is a handful of simple functions allowing basic manipulations on arrays. ============================================================= Important note: ^^^^^^^^^^^^^^^ In the output of all slicing functions included here, any useless dimensions vanish! ============================================================= This warning deserves a clear explanation. In short: all functions below (except the transpose function) will flatten their output as much as possible, removing any [1] dimension(s) from the definition of the variable returned. Detailed explanation: Suppose you have $Data[140][23] a 2D array and you want to extract some data from it. First say you need to work with the rows 5 and 6 of your array (remember AutoIt indices start at 0). You need to copy this subarray from $Data and perform some processing on it. You will see below that you can use function _ArrayPart to perform just that and you could write something like: ;; position of the topmost-leftmost element to copy is [5][0] ;; dimensions of the requested output is [2][23] (two full rows of 23 elements each) Local $sub56 = _ArrayPart($Data, 5, 0, 2, UBound($Data, 2)) ... PerformSuperProcess($sub56) ... In the example above $sub56 is a 2D array of dimensions [2][23]. No surprise here. Now imagine you also need to play with the data contained in the third row. AutoIt doesn't offer the possibility to manipulate $Data[2] and treat it a 1D array with 23 elements. Again function _ArrayPart can help you: ;; position of the topmost-leftmost element to copy is [3][0] ;; dimensions of the requested output is [1][23] (one full row) Local $sub3 = _ArrayPart($Data, 3, 0, 1, UBound($Data, 2)) ... DoSomethingWith($sub3) ... In this example $sub3 is now a 1D array of dimension [23]. Why? Because I found that returning in this particular case a 2D array of dimensions [1][23] would be unpractical. Leaving the dimensions of the output array as [1][23] would force you to access any element with superfous [0] indexing, like in: If $sub3[0][5] = 3 And $sub3[0][11] <> 0 Then It is for this reason that when 1 is given for a requested dimension parameter, the corresponding dimension in the output array is "flaten" down to the previous level. As a consequence if you extract a single element of a list (1d), a table (2D) or any 3D or 4D array, then the result is a "flat" variable, not an array. Visually the functions work as follows: $a = [ a, b, c, d, e, f ] _ListHead($a, 4) --> [a, b, c, d] _ListHead($a, 1) --> a <-- not [a] _ListTail($a, 4) --> [c, d, e, f] _ListTail($a, 1) --> f <-- not [f] _ListPart($a, 2, 3) --> [c, d, e] _ListPart($a, 2, 1) --> c <-- not [c] [[ a, b, c ] $a = [ d, e, f ] _TableHead($a, 1, 1) --> a <-- not [[a]] [ g, h, i ]] _TableHead($a, 1, 2) --> [a, b] <-- not [[a, b]] _TableHead($a, 2, 2) --> [[a, b], [d, e]] -------- Functions for working on lists (1D arrays) _ListHead($a, $length) input: $a is an array of dimension 1 $length is an integer (possibly in string form) specifying the dimension of the output output: 1D array of the first $length elements of $a if UBound($a, 1) > $length > 1 element $a[0] if $length = 1 _ListTail($a, $length) input: $a is an array of dimension 1 output: 1D array of the last $length elements of $a if UBound($a, 1) > $length > 1 last element of $a if $length = 1 _ListPart($a, $start, $length) input: $a is an array of dimension 1 $start is an integer (possibly in string form) specifying the start location in $a of the output $length is an integer (possibly in string form) specifying the dimension of the output output: 1D array of the first $length elements of $a if UBound($a, 1) > $length > 1 element $a[0] if $length = 1 -------- Functions for working on tables (2D arrays) _TableHead($a, $length) input: $a is an array of dimension 2 $length is a 1D array of 2 integers (possibly in string form) specifying the dimensions of the output output: top-left subarray of $a with dimensions given by $length _TableTail($a, $length) input: $a is an array of dimension 2 $length is a 1D array of 2 integers (possibly in string form) specifying the dimensions of the output output: bottom-right subarray of $a with dimensions given by $length _TablePart($a, $start, $length) input: $a is an array of dimension 2 $start is a 1D array of 2 integers (possibly in string form) specifying the start location in $a of the output $length is a 1D array of 2 integers (possibly in string form) specifying the dimensions of the output output: subarray of $a with first element located at $start and with dimensions given by $length -------- Functions for working on 3D and 4D arrays _ArrayPart($a, $start, $length) input: $a is an array of dimension 3 $start is a 1D array of 3 integers (possibly in string form) specifying the start location in $a of the output $length is a 1D array of 3 integers (possibly in string form) specifying the dimensions of the output output: subarray of $a with first element located at $start and with dimensions given by $length _ArrayPart($a, $start, $length) input: $a is an array of dimension 4 $start is a 1D array of 4 integers (possibly in string form) specifying the start location in $a of the output $length is a 1D array of 4 integers (possibly in string form) specifying the dimensions of the output output: subarray of $a with first element located at $start and with dimensions given by $length -------- Transpose functions work on 2D, 3D and 4D arrays _Transpose($a) input: $a is an array of dimension 2 output: the transpose of matrix $a (exchange of rows and columns) _Transpose($a, $td1 = 1, $td2 = 2) input: $a is an array of dimension 3 $td1 and $td2 are 2 integers specifying which dimensions of $a to exchange output: the ($td1,$td2)transpose of matrix $a (exchange of dimensions $td1 and $td2) _Transpose($a, $td1 = 1, $td2 = 2) input: $a is an array of dimension 4 $td1 and $td2 are 2 integers specifying which dimensions of $a to exchange output: the ($td1,$td2)transpose of matrix $a (exchange of dimensions $td1 and $td2) -------------------------------------------------------------------------------------------------- #ce ;; functionally equivalent to _ListPart($a, 0, $length) Func _ListHead(Const ByRef $a, $ln) Local $l1, $ret If Not IsArray($a) Then Return SetError(1, 1, 0) EndIf $l1 = Int(Number($ln)) If UBound($a, 0) <> 1 Then Return SetError(1, 2, 0) ElseIf $l1 < 1 Or $l1 > UBound($a, 1) Then Return SetError(1, 4, 0) EndIf If $l1 == 1 Then Local $ret = $a[0] Else ;; The following coding option may be sub-optimal when ;; extracting only few top rows from a very large array ;; or when the cost of copying the input array is really ;; significant, in which case a For loop would perform ;; better. ;; Nonetheless this should work well with most "common" cases. Local $ret = $a ReDim $ret[$l1] EndIf Return($ret) EndFunc ;; same as _ListPart($a, UBound($a, 1) - $length, $length) Func _ListTail(Const ByRef $a, $ln) Local $d1, $l1, $ret If Not IsArray($a) Then Return SetError(1, 1, 0) EndIf $d1 = UBound($a, 1) $l1 = Int(Number($ln)) If UBound($a, 0) <> 1 Then Return SetError(1, 2, 0) ElseIf $l1 < 1 Or $l1 > $d1 Then Return SetError(1, 4, 0) EndIf If $l1 == 1 Then Local $ret = $a[$d1 - 1] Else Dim $ret[$l1] $d1 -= $l1 For $i = 0 To $l1 - 1 $ret[$i] = $a[$d1 + $i] Next EndIf Return($ret) EndFunc Func _ListPart(Const ByRef $a, $st, $ln) Local $d1, $s1, $l1, $ret If Not IsArray($a) Then Return SetError(1, 1, 0) EndIf $d1 = UBound($a, 1) $s1 = Int(Number($st)) $l1 = Int(Number($ln)) If UBound($a, 0) <> 1 Then Return SetError(1, 2, 0) ElseIf $s1 < 0 Or $s1 >= $d1 Then Return SetError(1, 3, 0) ElseIf $l1 < 2 Or $s1 + $l1 > $d1 Then Return SetError(1, 4, 0) EndIf If $l1 == 1 Then Return $a[$s1] Dim $ret[$l1] $d1 -= $s1 For $i = 0 To $l1 - 1 $ret[$i] = $a[$s1 + $i] Next Return($ret) EndFunc Func _TableHead(Const ByRef $a, Const $ln1, Const $ln2) Local $l1, $l2, $ret If Not IsArray($a) Then Return SetError(1, 1, 0) ElseIf UBound($a, 0) <> 2 Then Return SetError(1, 2, 0) EndIf $l1 = Int(Number($ln1)) $l2 = Int(Number($ln2)) If $l1 < 1 Or $l2 < 1 Or $l1 > UBound($a, 1) Or $l2 > UBound($a, 2) Then Return SetError(1, 4, 0) EndIf If $l1 == 1 And $l2 == 1 Then Local $ret = $a[0][0] ElseIf $l1 == 1 Then Dim $ret[$l2] For $j = 0 To $l2 - 1 $ret[$j] = $a[0][$j] Next ElseIf $l2 == 1 Then Dim $ret[$l1] For $i = 0 To $l1 - 1 $ret[$i] = $a[$i][0] Next Else Dim $ret = $a ;; this implies copy of the whole array and truncation to desired dimensions ReDim $ret[$l1][$l2] ;; which can be slow for pathological cases: use For loop below in such cases ;~ Dim $ret[$l1][$l2] ;~ For $i = 0 To $l1 - 1 ;~ For $j = 0 To $l2 - 1 ;~ $ret[$i][$j] = $a[$i][$j] ;~ Next ;~ Next EndIf Return($ret) EndFunc Func _TableTail(Const ByRef $a, Const $ln1, Const $ln2) Local $l1, $l2, $d1, $d2, $ret If Not IsArray($a) Then Return SetError(1, 1, 0) ElseIf UBound($a, 0) <> 2 Then Return SetError(1, 2, 0) EndIf $l1 = Int(Number($ln1)) $l2 = Int(Number($ln2)) $d1 = UBound($a, 1) $d2 = UBound($a, 2) If $l1 < 1 Or $l2 < 1 Or $l1 > $d1 Or $l2 > $d2 Then Return SetError(1, 4, 0) EndIf $d1 -= $l1 $d2 -= $l2 If $l1 == 1 And $l2 == 1 Then Local $ret = $a[$d1][$d2] ElseIf $l1 == 1 Then Dim $ret[$l2] For $j = 0 To $l2 - 1 $ret[$j] = $a[$d1][$d2 + $j] Next ElseIf $l2 == 1 Then Dim $ret[$l1] For $i = 0 To $l1 - 1 $ret[$i] = $a[$d1 + $i][$d2] Next Else Dim $ret[$l1][$l2] For $i = 0 To $l1 - 1 For $j = 0 To $l2 - 1 $ret[$i][$j] = $a[$d1 + $i][$d2 + $j] Next Next EndIf Return($ret) EndFunc Func _TablePart(Const ByRef $a, Const $st1, Const $st2, Const $ln1, Const $ln2) Local $s1, $s2, $l1, $l2, $d1, $d2, $ret If Not IsArray($a) Then Return SetError(1, 1, 0) ElseIf UBound($a, 0) <> 2 Then Return SetError(1, 2, 0) EndIf $s1 = Int(Number($st1)) $s2 = Int(Number($st2)) $l1 = Int(Number($ln1)) $l2 = Int(Number($ln2)) $d1 = UBound($a, 1) $d2 = UBound($a, 2) If $s1 < 0 Or $s1 >= $d1 Or $s2 < 0 Or $s2 >= $d2 Then Return SetError(1, 3, 0) ElseIf $l1 < 1 Or $l2 < 1 Or $s1 + $l1 > $d1 Or $s2 + $l2 > $d2 Then Return SetError(1, 4, 0) EndIf If $l1 == 1 And $l2 == 1 Then Local $ret = $a[$s1][$s2] ElseIf $l1 == 1 Then Dim $ret[$l2] For $j = 0 To $l2 - 1 $ret[$j] = $a[$s1][$s2 + $j] Next ElseIf $l2 == 1 Then Dim $ret[$l1] For $i = 0 To $l1 - 1 $ret[$i] = $a[$s1 + $i][$s2] Next Else Dim $ret[$l1][$l2] For $i = 0 To $l1 - 1 For $j = 0 To $l2 - 1 $ret[$i][$j] = $a[$s1 + $i][$s2 + $j] Next Next EndIf Return($ret) EndFunc Func _ArrayPart(Const ByRef $a, Const $st1, Const $st2, Const $st3, Const $p4, Const $p5, Const $p6, Const $p7 = 0, Const $p8 = 0) Local $s1, $s2, $s3, $s4, $l1, $l2, $l3, $l4, $d1, $d2, $d3, $d4, $ub, $ret If Not IsArray($a) Then Return SetError(1, 1, 0) EndIf $ub = UBound($a, 0) $d1 = UBound($a, 1) $d2 = UBound($a, 2) $d3 = UBound($a, 3) $s1 = Int(Number($st1)) $s2 = Int(Number($st2)) $s3 = Int(Number($st3)) Switch $ub Case 3 $l1 = Int(Number($p4)) $l2 = Int(Number($p5)) $l3 = Int(Number($p6)) Case 4 $d4 = UBound($a, 4) $s4 = Int(Number($p4)) $l1 = Int(Number($p5)) $l2 = Int(Number($p6)) $l3 = Int(Number($p7)) $l4 = Int(Number($p8)) Case Else Return SetError(1, 2, 0) EndSwitch If $s1 < 0 Or $s1 >= $d1 Or $s2 < 0 Or $s2 >= $d2 Or $s3 < 0 Or $s3 >= $d3 Then Return SetError(1, 3, 0) ElseIf $l1 < 1 Or $l2 < 1 Or $l3 < 1 Or $s1 + $l1 > $d1 Or $s2 + $l2 > $d2 Or $s3 + $l3 > $d3 Then Return SetError(1, 4, 0) EndIf Switch $ub Case 3 $ret = __Array3Part($a, $s1, $s2, $s3, $l1, $l2, $l3, $d1, $d2, $d3) Case 4 If $s4 < 0 Or $s4 >= $d4 Then Return SetError(1, 3, 0) ElseIf $l4 < 1 Or $s4 + $l4 > $d4 Then Return SetError(1, 4, 0) EndIf $ret = __Array4Part($a, $s1, $s2, $s3, $s4, $l1, $l2, $l3, $l4, $d1, $d2, $d3, $d4) EndSwitch Return SetError(@error, @extended, $ret) EndFunc Func __Array3Part($a, $s1, $s2, $s3, $l1, $l2, $l3, $d1, $d2, $d3) Local $ret If $l1 == 1 And $l2 == 1 And $l3 == 1 Then Local $ret = $a[$s1][$s2][$s3] ElseIf $l1 == 1 And $l2 == 1 And $l3 > 1 Then Dim $ret[$l3] For $k = 0 To $l3 - 1 $ret[$k] = $a[$s1][$s2][$s3 + $k] Next ElseIf $l1 == 1 And $l2 > 1 And $l3 == 1 Then Dim $ret[$l2] For $j = 0 To $l2 - 1 $ret[$j] = $a[$s1][$s2 + $j][$s3] Next ElseIf $l1 == 1 And $l2 > 1 And $l3 > 1 Then Dim $ret[$l2][$l3] For $j = 0 To $l2 - 1 For $k = 0 To $l3 - 1 $ret[$j][$k] = $a[$s1][$s2 + $j][$s3 + $k] Next Next ElseIf $l1 > 1 And $l2 == 1 And $l3 == 1 Then Dim $ret[$l1] For $i = 0 To $l1 - 1 $ret[$i] = $a[$s1 + $i][$s2][$s3] Next ElseIf $l1 > 1 And $l2 == 1 And $l3 > 1 Then Dim $ret[$l1][$l3] For $i = 0 To $l1 - 1 For $k = 0 To $l3 - 1 $ret[$i][$k] = $a[$s1 + $i][$s2][$s3 + $k] Next Next ElseIf $l1 > 1 And $l2 > 1 And $l3 == 1 Then Dim $ret[$l1][$l2] For $i = 0 To $l1 - 1 For $j = 0 To $l2 - 1 $ret[$i][$j] = $a[$s1 + $i][$s2 + $j][$s3] Next Next Else Dim $ret[$l1][$l2][$l3] For $i = 0 To $l1 - 1 For $j = 0 To $l2 - 1 For $k = 0 To $l3 - 1 $ret[$i][$j][$k] = $a[$s1 + $i][$s2 + $j][$s3 + $k] Next Next Next EndIf Return($ret) EndFunc Func __Array4Part(Const ByRef $a, $s1, $s2, $s3, $s4, $l1, $l2, $l3, $l4, $d1, $d2, $d3, $d4) Local $ret If $l1 == 1 And $l2 == 1 And $l3 == 1 And $l4 == 1 Then $ret = $a[$s1][$s2][$s3][$s4] ElseIf $l1 == 1 And $l2 == 1 And $l3 == 1 And $l4 > 1 Then Dim $ret[$l4] For $l = 0 To $l4 - 1 $ret[$l] = $a[$s1][$s2][$s3][$s4 + $l] Next ElseIf $l1 == 1 And $l2 == 1 And $l3 > 1 And $l4 == 1 Then Dim $ret[$l3] For $k = 0 To $l3 - 1 $ret[$k] = $a[$s1][$s2][$s3 + $k][$s4] Next ElseIf $l1 == 1 And $l2 == 1 And $l3 > 1 And $l4 > 1 Then Dim $ret[$l3][$l4] For $k = 0 To $l3 - 1 For $l = 0 To $l4 - 1 $ret[$k][$l] = $a[$s1][$s2][$s3 + $k][$s4 + $l] Next Next ElseIf $l1 == 1 And $l2 > 1 And $l3 == 1 And $l4 == 1 Then Dim $ret[$l2] For $j = 0 To $l2 - 1 $ret[$j] = $a[$s1][$s2 + $j][$s3][$s4] Next ElseIf $l1 == 1 And $l2 > 1 And $l3 == 1 And $l4 > 1 Then Dim $ret[$l2][$l4] For $j = 0 To $l2 - 1 For $l = 0 To $l4 - 1 $ret[$j][$l] = $a[$s1][$s2 + $j][$s3][$s4 + $l] Next Next ElseIf $l1 == 1 And $l2 > 1 And $l3 > 1 And $l4 == 1 Then Dim $ret[$l2][$l3] For $j = 0 To $l2 - 1 For $k = 0 To $l3 - 1 $ret[$j][$k] = $a[$s1][$s2 + $j][$s3 + $k][$s4] Next Next ElseIf $l1 == 1 And $l2 > 1 And $l3 > 1 And $l4 > 1 Then Dim $ret[$l2][$l3][$l4] For $j = 0 To $l2 - 1 For $k = 0 To $l3 - 1 For $l = 0 To $l4 - 1 $ret[$j][$k][$l] = $a[$s1][$s2 + $j][$s3 + $k][$s4 + $l] Next Next Next ElseIf $l1 > 1 And $l2 == 1 And $l3 == 1 And $l4 == 1 Then Dim $ret[$l1] For $i = 0 To $l1 - 1 $ret[$i] = $a[$s1 + $i][$s2][$s3][$s4] Next ElseIf $l1 > 1 And $l2 == 1 And $l3 == 1 And $l4 > 1 Then Dim $ret[$l1][$l4] For $i = 0 To $l1 - 1 For $l = 0 To $l4 - 1 $ret[$i][$l] = $a[$s1 + $i][$s2][$s3][$s4 + $l] Next Next ElseIf $l1 > 1 And $l2 == 1 And $l3 > 1 And $l4 == 1 Then Dim $ret[$l1][$l3] For $i = 0 To $l1 - 1 For $k = 0 To $l3 - 1 $ret[$i][$k] = $a[$s1 + $i][$s2][$s3 + $k][$s4] Next Next ElseIf $l1 > 1 And $l2 == 1 And $l3 > 1 And $l4 > 1 Then Dim $ret[$l1][$l3][$l4] For $i = 0 To $l1 - 1 For $k = 0 To $l3 - 1 For $l = 0 To $l4 - 1 $ret[$i][$k][$l] = $a[$s1 + $i][$s2][$s3 + $k][$s4 + $l] Next Next Next ElseIf $l1 > 1 And $l2 > 1 And $l3 == 1 And $l4 == 1 Then Dim $ret[$l1][$l2] For $i = 0 To $l1 - 1 For $j = 0 To $l2 - 1 $ret[$i][$j] = $a[$s1 + $i][$s2 + $j][$s3][$s4] Next Next ElseIf $l1 > 1 And $l2 > 1 And $l3 == 1 And $l4 > 1 Then Dim $ret[$l1][$l2][$l4] For $i = 0 To $l1 - 1 For $j = 0 To $l2 - 1 For $l = 0 To $l4 - 1 $ret[$i][$j][$l] = $a[$s1 + $i][$s2 + $j][$s3][$s4 + $l] Next Next Next ElseIf $l1 > 1 And $l2 > 1 And $l3 > 1 And $l4 == 1 Then Dim $ret[$l1][$l2][$l3] For $i = 0 To $l1 - 1 For $j = 0 To $l2 - 1 For $k = 0 To $l3 - 1 $ret[$i][$j][$k] = $a[$s1 + $i][$s2 + $j][$s3 + $k][$s4] Next Next Next Else Dim $ret[$l1][$l2][$l3][$l4] For $i = 0 To $l1 - 1 For $j = 0 To $l2 - 1 For $k = 0 To $l3 - 1 For $l = 0 To $l4 - 1 $ret[$i][$j][$k][$l] = $a[$s1 + $i][$s2 + $j][$s3 + $k][$s4 + $l] Next Next Next Next EndIf Return($ret) EndFunc Func _Transpose(Const ByRef $a, $td1 = 1, $td2 = 2) Local $ub, $tmp, $trd1, $trd2, $ret If Not IsArray($a) Then Return SetError(1, 1, 0) EndIf $ub = UBound($a, 0) $trd1 = Int(Number($td1)) $trd2 = Int(Number($td2)) If $trd1 < 1 Or $trd1 > $ub Or $trd2 < 1 Or $trd2 > $ub Or $trd1 == $trd2 Then Return SetError(1, 5, 0) EndIf If $trd1 > $trd2 Then $tmp = $trd2 $trd2 = $trd1 $trd1 = $tmp EndIf Switch $ub Case 2 $ret = __Transpose2($a) Case 3 $ret = __Transpose3($a, $trd1, $trd2) Case 4 $ret = __Transpose4($a, $trd1, $trd2) ;; You are of course welcome to add next Cases from 5 up to 64 (max dimensions in AutoIt) ;; but be warned that it soon becomes a little mess of indices and the usefulness for higher ;; dimensions might be marginal. The current limit of 4 seems a good compromise. Case Else Return SetError(1, 7, 0) EndSwitch Return SetError(@error, @extended, $ret) EndFunc Func __Transpose2($a) Local $d1, $d2 $d1 = UBound($a, 1) $d2 = UBound($a, 2) Dim $ret[$d2][$d1] For $i = 0 To $d1 - 1 For $j = 0 To $d2 - 1 $ret[$j][$i] = $a[$i][$j] Next Next Return($ret) EndFunc Func __Transpose3(Const ByRef $a, $trd1, $trd2) Local $d1, $d2, $d3 $d1 = UBound($a, 1) $d2 = UBound($a, 2) $d3 = UBound($a, 3) If $trd1 == 1 And $trd2 == 2 Then Dim $ret[$d2][$d1][$d3] For $i = 0 To $d1 - 1 For $j = 0 To $d2 - 1 For $k = 0 To $d3 - 1 $ret[$j][$i][$k] = $a[$i][$j][$k] Next Next Next ElseIf $trd1 == 1 And $trd2 == 3 Then Dim $ret[$d3][$d2][$d1] For $i = 0 To $d1 - 1 For $j = 0 To $d2 - 1 For $k = 0 To $d3 - 1 $ret[$k][$j][$i] = $a[$i][$j][$k] Next Next Next Else ; must be transposing 2 and 3 Dim $ret[$d1][$d3][$d2] For $i = 0 To $d1 - 1 For $j = 0 To $d2 - 1 For $k = 0 To $d3 - 1 $ret[$i][$k][$j] = $a[$i][$j][$k] Next Next Next EndIf Return($ret) EndFunc Func __Transpose4(Const ByRef $a, $trd1, $trd2) Local $d1, $d2, $d3, $d4 $d1 = UBound($a, 1) $d2 = UBound($a, 2) $d3 = UBound($a, 3) $d4 = UBound($a, 4) If $trd1 == 1 And $trd2 == 2 Then Dim $ret[$d2][$d1][$d3][$d4] For $i = 0 To $d1 - 1 For $j = 0 To $d2 - 1 For $k = 0 To $d3 - 1 For $l = 0 To $d4 - 1 $ret[$j][$i][$k][$l] = $a[$i][$j][$k][$l] Next Next Next Next ElseIf $trd1 == 1 And $trd2 == 3 Then Dim $ret[$d3][$d2][$d1][$d4] For $i = 0 To $d1 - 1 For $j = 0 To $d2 - 1 For $k = 0 To $d3 - 1 For $l = 0 To $d4 - 1 $ret[$k][$j][$i][$l] = $a[$i][$j][$k][$l] Next Next Next Next ElseIf $trd1 == 1 And $trd2 == 4 Then Dim $ret[$d4][$d2][$d3][$d1] For $i = 0 To $d1 - 1 For $j = 0 To $d2 - 1 For $k = 0 To $d3 - 1 For $l = 0 To $d4 - 1 $ret[$l][$j][$k][$i] = $a[$i][$j][$k][$l] Next Next Next Next ElseIf $trd1 == 2 And $trd2 == 3 Then Dim $ret[$d1][$d3][$d2][$d4] For $i = 0 To $d1 - 1 For $j = 0 To $d2 - 1 For $k = 0 To $d3 - 1 For $l = 0 To $d4 - 1 $ret[$i][$k][$j][$l] = $a[$i][$j][$k][$l] Next Next Next Next ElseIf $trd1 == 2 And $trd2 == 4 Then Dim $ret[$d1][$d4][$d3][$d2] For $i = 0 To $d1 - 1 For $j = 0 To $d2 - 1 For $k = 0 To $d3 - 1 For $l = 0 To $d4 - 1 $ret[$i][$l][$k][$j] = $a[$i][$j][$k][$l] Next Next Next Next Else ; must be transposing 3 and 4 Dim $ret[$d1][$d2][$d4][$d3] For $i = 0 To $d1 - 1 For $j = 0 To $d2 - 1 For $k = 0 To $d3 - 1 For $l = 0 To $d4 - 1 $ret[$i][$j][$l][$k] = $a[$i][$j][$k][$l] Next Next Next Next EndIf Return($ret) EndFunc #cs ======================== quick, dirty and very incomplete test "suite" ========================= #include Local $ar, _ $t1[13] = ["ab", "cd", "ef", "gh", "ij", "kl", "mn", "op", "qr", "st", "uv", "wx", "yz"], _ $t2[6][4] = [ ["a0", "a1", "a2", "a3"], _ ["b0", "b1", "b2", "b3"], _ ["c0", "c1", "c2", "c3"], _ ["d0", "d1", "d2", "d3"], _ ["e0", "e1", "e2", "e3"], _ ["f0", "f1", "f2", "f3"] ], _ $d2[2] = [4, "2"], _ $st2[2] = [2, 1], _ $sl2[2] = [1, 2], _ $ln2[2] = [2, 3], _ $st3[3] = [1, 1, 1], _ $t3[3][4][5] For $i = 0 To 2 For $j = 0 To 3 For $k = 0 To 4 $t3[$i][$j][$k] = $i & $j & $k Next Next Next $ar = _ListHead($t1, 4) If @error Then MsgBox(0, "Error", "Error code = " & @extended) _ArrayDisplay($ar, "_ListHead($t1, 4) test") $ar = _ListPart($t1, 0, 4) If @error Then MsgBox(0, "Error", "Error code = " & @extended) _ArrayDisplay($ar, "_ListPart($t1, 0, 4) test (same as before)") $ar = _ListTail($t1, 7) If @error Then MsgBox(0, "Error", "Error code = " & @extended) _ArrayDisplay($ar, "_ListTail($t1, 7) test") $ar = _ListPart($t1, 6, 7) If @error Then MsgBox(0, "Error", "Error code = " & @extended) _ArrayDisplay($ar, "_ListPart($t1, 6, 7) test (same as before)") $ar = _ListPart($t1, 2, "5") If @error Then MsgBox(0, "Error", "Error code = " & @extended) _ArrayDisplay($ar, "_ListPart($t1, 2, 5) test") $ar = _ListPart($t1, 12, 1) If @error Then MsgBox(0, "Error", "Error code = " & @extended) _ArrayDisplay($ar, "_ListPart($t1, 12, 1) test") $ar = _TableHead($t2, $d2) If @error Then MsgBox(0, "Error", "Error code = " & @extended) _ArrayDisplay($ar, "_TableHead($t2, [4, 2]) test") $ar = _TableTail($t2, $d2) If @error Then MsgBox(0, "Error", "Error code = " & @extended) _ArrayDisplay($ar, "_TableTail($t2, [4, 2]) test") $ar = _ArrayPart($t2, $st2, $ln2) If @error Then MsgBox(0, "Error", "Error code = " & @extended) _ArrayDisplay($ar, "_ArrayPart($t2, [2, 1], [2, 3]) test") $ar = _ArrayPart($t2, $st2, $ln2) If @error Then MsgBox(0, "Error", "Error code = " & @extended) _ArrayDisplay($ar, "_ArrayPart($t2, [2, 1], [2, 3]) test") $ar = _ArrayPart($t2, $st2, $sl2) If @error Then MsgBox(0, "Error", "Error code = " & @extended) _ArrayDisplay($ar, "_ArrayPart($t2, [2, 1], [1, 2]) test") $ar = _Array2Transpose($t2) If @error Then MsgBox(0, "Error", "Error code = " & @extended) _ArrayDisplay($ar, "_Array2Transpose($t2) test") $ar = _TableTail($t2, $d2) If @error Then MsgBox(0, "Error", "Error code = " & @extended) _ArrayDisplay($ar, "_TableTail($t2, [4, 2]) test") Dim $d[2] = [3, 1] $ar = _TableTail($t2, $d) If @error Then MsgBox(0, "Error", "Error code = " & @extended) _ArrayDisplay($ar, "_TableTail($t2, [3, 1]) test") Dim $d[2] = [1, 3] $ar = _TableTail($t2, $d) If @error Then MsgBox(0, "Error", "Error code = " & @extended) _ArrayDisplay($ar, "_TableTail($t2, [1, 3]) test") $ar = _TableHead($t2, $d2) If @error Then MsgBox(0, "Error", "Error code = " & @extended) _ArrayDisplay($ar, "_TableHead($t2, [4, 2]) test") Dim $d[2] = [3, 1] $ar = _TableHead($t2, $d) If @error Then MsgBox(0, "Error", "Error code = " & @extended) _ArrayDisplay($ar, "_TableHead($t2, [3, 1]) test") Dim $d[2] = [1, 3] $ar = _TableHead($t2, $d) If @error Then MsgBox(0, "Error", "Error code = " & @extended) _ArrayDisplay($ar, "_TableHead($t2, [1, 3]) test") $ar = _ArrayPart($t2, $st2, $ln2) If @error Then MsgBox(0, "Error", "Error code = " & @extended) _ArrayDisplay($ar, "_ArrayPart($t2, [2, 1], [2, 3]) test") Dim $d[2] = [3, 1] $ar = _ArrayPart($t2, $st2, $d) If @error Then MsgBox(0, "Error", "Error code = " & @extended) _ArrayDisplay($ar, "_ArrayPart($t2, [2, 1], [3, 1]) test") Dim $d[2] = [1, 3] $ar = _ArrayPart($t2, $st2, $d) If @error Then MsgBox(0, "Error", "Error code = " & @extended) _ArrayDisplay($ar, "_ArrayPart($t2, [2, 1], [1, 3]) test") Dim $d[3] = [2, 2, 2] $ar = _ArrayPart($t3, $st3, $d) If @error Then MsgBox(0, "Error", "Error code = " & @extended) ;~ _ArrayDisplay($ar, "_ArrayPart($t3, [1, 1, 2], [2, 2, 2]) test") Dim $d[3] = [1, 2, 2] $ar = _ArrayPart($t3, $st3, $d) If @error Then MsgBox(0, "Error", "Error code = " & @extended) _ArrayDisplay($ar, "_ArrayPart($t3, [1, 1, 1], [1, 2, 2]) test") Dim $d[3] = [2, 1, 2] $ar = _ArrayPart($t3, $st3, $d) If @error Then MsgBox(0, "Error", "Error code = " & @extended) _ArrayDisplay($ar, "_ArrayPart($t3, [1, 1, 1], [2, 1, 2]) test") Dim $d[3] = [2, 2, 1] $ar = _ArrayPart($t3, $st3, $d) If @error Then MsgBox(0, "Error", "Error code = " & @extended) _ArrayDisplay($ar, "_ArrayPart($t3, [1, 1, 1], [2, 2, 1]) test") EndIf #ce