# READ MULTIDIMENSIONAL ARRAY FROM STRING?

## Recommended Posts

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?

```;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```

##### Share on other sites

The solution involves the use of the little function "Equals" (shown below)

```;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```

##### Share on other sites

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.

## Create an account

Register a new account

• ### Recently Browsing   0 members

×

• Wiki

• Back

• #### Beta

• Git
• FAQ
• Our Picks
×
• Create New...