kenn Posted November 28, 2005 Share Posted November 28, 2005 Below are a test program and 3 functions. The FIRST function packs a multidimensional array into a string. The SECOND function tries to read the array back again from the string, but FAILS because statements like Assign('x[0]', 5) are not (yet) supported. The THIRD function solves the problem for arrays of up to 3 dimensions, and could be extended for any number of dimensions, but in an awkward way. Any alternatives? expandcollapse popup;TEST PROGRAM ;build array $x dim $x[1][2][3] = [[[1, 2, 3], [4, 5, 6]]] ;build array $y dim $y[2][2] = [[100, 101], [102, 103]] ;put array $y into array $x to make things more interesting $x[0][1][0] = $y ;test of ArrayToString (works) $s = ArrayToString($x) MsgBox(0, 'ArrayToString: array in array', $s) ;make sure $x is empty dim $x[1][2][3] dim $y[2][2] $x[0][1][0] = $y $s2 = ArrayToString($x) MsgBox(0, 'ArrayToString: see, $x is empty!', $s2) ;save string because StringToArray eats it $s2 = $s ;put string back into array (1st attempt, DOESN'T WORK) StringToArray($s, $x) MsgBox(0, 'StringToArray', ArrayToString($x)) ;put string back into array (2nd attempt, works) StringToArray2($s2, $x) MsgBox(0, 'StringToArray2', ArrayToString($x)) exit ;pack multidimensional array into string with comma separator func ArrayToString(ByRef $array) local $elem = '$array' ;element of array local $i ;index into subscripts local $item ;item of string local $ix[ubound($array, 0)] ;array subscripts (up to 64) local $string ;array as string for $i = 0 to UBound($array, 0) - 1 $elem = $elem & '[$ix[' & $i & ']]' next while TRUE $item = Execute($elem) if IsArray($item) then $item = ArrayToString($item) elseif StringInStr($item, ',') <> 0 then MsgBox(16, 'array element contains separator', '') exit endif $string = $string & ',' & $item ;increment array indices to get next element for $i = UBound($array, 0) - 1 to 0 step -1 $ix[$i] = $ix[$i] + 1 if $ix[$i] <> UBound($array, $i + 1) then exitloop if $i = 0 then return StringMid($string, 2) $ix[$i] = 0 next wend endfunc ;N.B. THIS DOESN'T WORK! (because "Assign" to array element doesn't work!) ;rebuild multidimensional array from string ;N.B. eats $string func StringToArray(ByRef $string, ByRef $array) local $elem = '$array' ;element of array local $i ;index into subscripts local $item ;item of array local $ix[ubound($array, 0)] ;array subscripts if IsArray($string) = FALSE then $string = StringSplit($string, ',') $string[0] = 1 endif for $i = 0 to UBound($array, 0) - 1 $elem = $elem & '[$ix[' & $i & ']]' next while TRUE $item = Execute($elem) if IsArray($item) then StringToArray($string, $item) else if IsString($item) then $item = $string[$string[0]] else $item = Number($string[$string[0]]) endif $string[0] = $string[0] + 1 endif ;problem is with "Assign" to array element Assign(StringMid($elem, 2), $item) ;increment array indices to get next element for $i = UBound($array, 0) - 1 to 0 step -1 $ix[$i] = $ix[$i] + 1 if $ix[$i] <> UBound($array, $i + 1) then exitloop if $i = 0 then return $ix[$i] = 0 next wend endfunc ;rebuild multidimensional array from string (1, 2 or 3 dimensions only) ;N.B. eats $string func StringToArray2(ByRef $string, ByRef $array) local $elem = '$array' ;element of array local $i ;index into subscripts local $item ;item of array local $ix[ubound($array, 0)] ;array subscripts if IsArray($string) = FALSE then $string = StringSplit($string, ',') $string[0] = 1 endif for $i = 0 to UBound($array, 0) - 1 $elem = $elem & '[$ix[' & $i & ']]' next while TRUE $item = Execute($elem) if IsArray($item) then StringToArray2($string, $item) else if IsString($item) then $item = $string[$string[0]] else $item = Number($string[$string[0]]) endif $string[0] = $string[0] + 1 endif switch UBound($array, 0) case 1 $array[$ix[0]] = $item case 2 $array[$ix[0]][$ix[1]] = $item case 3 $array[$ix[0]][$ix[1]][$ix[2]] = $item case else MsgBox(16, 'too many dimensions', '') exit endswitch ;increment array indices to get next element for $i = UBound($array, 0) - 1 to 0 step -1 $ix[$i] = $ix[$i] + 1 if $ix[$i] <> UBound($array, $i + 1) then exitloop if $i = 0 then return $ix[$i] = 0 next wend endfunc Link to comment Share on other sites More sharing options...
kenn Posted November 29, 2005 Author Share Posted November 29, 2005 The solution involves the use of the little function "Equals" (shown below) expandcollapse popup;TEST PROGRAM ;build array $x dim $x[1][2][3] = [[[1, 2, 3], [4, 5, 6]]] ;build array $y dim $y[2][2] = [[100, 101], [102, 103]] ;put array $y into array $x to make things more interesting $x[0][1][0] = $y ;pack array $x into string $s $s = ArrayToString($x) MsgBox(0, 'array $x is:', $s) ;make sure array $x is empty dim $x[1][2][3] dim $y[2][2] $x[0][1][0] = $y MsgBox(0, 'array $x is:', ArrayToString($x)) ;rebuild array $x from string $s StringToArray($s, $x) MsgBox(0, 'array $x is:', ArrayToString($x)) exit ;pack multidimensional array into string with comma separator func ArrayToString(ByRef $array) local $elem = '$array' ;element of array local $i ;index into subscripts local $item ;item of string local $ix[ubound($array, 0)] ;array subscripts (up to 64) local $string ;array as string for $i = 0 to UBound($array, 0) - 1 $elem = $elem & '[$ix[' & $i & ']]' next while TRUE $item = Execute($elem) if IsArray($item) then $item = ArrayToString($item) elseif StringInStr($item, ',') <> 0 then MsgBox(16, 'array element contains separator', '') exit endif $string = $string & ',' & $item for $i = UBound($array, 0) - 1 to 0 step -1 $ix[$i] = $ix[$i] + 1 if $ix[$i] <> UBound($array, $i + 1) then exitloop if $i = 0 then return StringMid($string, 2) $ix[$i] = 0 next wend endfunc ;rebuild multidimensional array from string func StringToArray(ByRef $string, ByRef $array) local $elem = '$array' ;element of array local $i ;index into subscripts local $item ;item of array local $ix[ubound($array, 0)] ;array subscripts (up to 64) local $stringCopy ;copy of original string if IsArray($string) = FALSE then $stringCopy = $string $string = StringSplit($string, ',') $string[0] = 1 endif for $i = 0 to UBound($array, 0) - 1 $elem = $elem & '[$ix[' & $i & ']]' next while TRUE $item = Execute($elem) if IsArray($item) then StringToArray($string, $item) else if IsString($item) then $item = $string[$string[0]] else $item = Number($string[$string[0]]) endif $string[0] = $string[0] + 1 endif Execute('Equals(' & $elem & ',$item)') for $i = UBound($array, 0) - 1 to 0 step -1 $ix[$i] = $ix[$i] + 1 if $ix[$i] <> UBound($array, $i + 1) then exitloop if $i = 0 then if $stringCopy <> '' then $string = $stringCopy return endif $ix[$i] = 0 next wend endfunc func Equals(ByRef $var, $val) $var = $val endfunc Link to comment Share on other sites More sharing options...
LxP Posted December 14, 2005 Share Posted December 14, 2005 Thanks for sharing, kenn. I've also been working on something requiring this -- a pair of functions to convert all AutoIt data types to and from strings (e.g. for saving to/loading from files) and also resorted to this workaround after many other failed attempts.In my opinion Assign() could (and probably should) be extended to handle array elements. I'm not sure how hard this might be though. Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now