Jump to content

How to set an element of a subarray of an array ?


Recommended Posts

I have an array of subarrays, eg:

local $a[3] = [ 1, 2, 3 ]
local $b[3] = [ 4, 5, 6 ]
local $c[2] = [ $a, $b ]

I can read read a subarray element of the array, as follows:

local $c12 = ($c[1])[2]     ; result: $c12 = 6

However, when I try to set a subarray element as follows, it fails:

($c[1])[2] = 12             ; this fails to set subarray element
local $c12 = ($c[1])[2]     ; result: $c12 = 6

How to set a subarray element ?

Thanks

Link to comment
Share on other sites

You are absolutely sure you need subarrays?
If yes, I think you need to extract $b to a temp array, modify the value and then update $c[1] with $b.

My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2022-02-19 - Version 1.6.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts
OutlookEX (2021-11-16 - Version 1.7.0.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX_GUI (2021-04-13 - Version 1.4.0.0) - Download
Outlook Tools (2019-07-22 - Version 0.6.0.0) - Download - General Help & Support - Wiki
PowerPoint (2021-08-31 - Version 1.5.0.0) - Download - General Help & Support - Example Scripts - Wiki
Task Scheduler (NEW 2022-07-28 - Version 1.6.0.1) - Download - General Help & Support - Wiki

Standard UDFs:
Excel - Example Scripts - Wiki
Word - Wiki

Tutorials:
ADO - Wiki
WebDriver - Wiki

 

Link to comment
Share on other sites

Here are some examples of dealing with elements of a sub-array which is an element in an array.

#include <Array.au3>

;  --------- Testing 1D array ----------
Local $b[] = [2, 3, 4], $a[4] = [1, $b, 5, 6]
_ArrayDisplay($a, "$a[4] = [1,$b,5,6]")

ConsoleWrite("($a[1])[1] = " & ($a[1])[1] & @CRLF)
_ASA($a[1], 1, 7)
ConsoleWrite("($a[1])[1] = " & ($a[1])[1] & @CRLF)

_ArrayDisplay($a[1], "3 to 7")

;  --------- Testing 2D array ----------
Local $b[] = [2, 3, 4], $a[2][4] = [[1, $b, 5, 6], [9, 10, 1, 12]]
_ArrayDisplay($a)

ConsoleWrite("($a[0][1])[2]  = " & ($a[0][1])[2] & @CRLF) ; = 4
;   ($a[0][1])[2] = 7 ; <- this does not work, produces " : error: Statement cannot be just an expression."
_ASA($a[0][1], 2, 7) ; In the 2D array of $a item $a[0][1] contains a 1D arr. _ASA() function is used to put the value 7 into ($a[0][1])[2]
ConsoleWrite("($a[0][1])[2]  = " & ($a[0][1])[2] & @CRLF) ; now = 7

_ArrayDisplay($a[0][1], "4 to 7")


;Assign to Sub-Array (ASA)
Func _ASA(ByRef $array, $iIndex, $Value)
    Local $aTemp = $array ;    Copy the array that is stored in an array's element to $aTemp (an array).
    $aTemp[$iIndex] = $Value ; Assign the new value.
    $array = $aTemp ;          Copy the modified Sub-array back to the element of the main array.
EndFunc   ;==>_ASA

 

Link to comment
Share on other sites

Hello guys
That's an interesting subject, thanks for your preceding comments.
If I understand well, neither Water nor Malkey modify SharpDressedMan's original $b array, right ?

At 1st, I thought Water was modifying it, as he refers to $b twice in his comment, ending with "then update $c[1] with $b", which applied to SharpDressedMan's script, could be interpreted like this :

#include <Array.au3>

local $a[3] = [ 1, 2, 3 ]
local $b[3] = [ 4, 5, 6 ]
local $c[2] = [ $a, $b ]

local $c12 = ($c[1])[2]
MsgBox(0 ,"Initial $c12" ,$c12) ;  6

;...........................
$b[2] = 12
local $c[2] = [ $a, $b ]
_ArrayDisplay($b, "$b changed (6 to 12)")
;...............................

_ArrayDisplay($c[1], "$c[1] changed (6 to 12)")

local $c12 = ($c[1])[2]
MsgBox(0 ,"Final $c12" ,$c12) ;  12


When Malkey's way keeps the original $b untouched :

#include <Array.au3>

local $a[3] = [ 1, 2, 3 ]
local $b[3] = [ 4, 5, 6 ]
local $c[2] = [ $a, $b ]

local $c12 = ($c[1])[2]
MsgBox(0 ,"Initial $c12" ,$c12) ;  6

;...........................
local $aTemp = $c[1]
$aTemp[2] = 12
$c[1] = $aTemp
_ArrayDisplay($b, "$b unchanged") ; 6
;...............................

_ArrayDisplay($c[1], "$c[1] changed (6 to 12)")

local $c12 = ($c[1])[2]
MsgBox(0 ,"Final $c12" ,$c12) ;  12

Both scripts give same result (12), but after re-reading Water's comment, I don't think at all he wanted to modify the original $b Array, as he also wrote : "extract $b to a temp array" which refers clearly to the b$ "included" in $c and not to the original $b as defined by local $b[] = ...

Also, what's really interesting in this thread is that it clarifies a point : is array $b included in array $c static ? Or is there a dynamic link between array $c and the original $b array ?

It's static, because as soon as this statement appears...
local $c[2] = [ $a, $b ]

...then a copy of $b is immediately included into $c, there is absolutely no dynamic link between $c and $b (that would have been interesting if we had a choice to create a dynamic link between both arrays, modifying an element in $b, like in the 1st script above, without having to redefine again local $c[2] = [ $a, $b ])

Before working on this thread and testing examples, as I never used "arrays within arrays", I didn't know if there was a dynamic link between arrays $c and $b (or between $c and $a), now i know :)

And to make sure, you can delete both original arrays a$ and b$, noticing that c$ is still populated : static !

#include <Array.au3>

local $a[3] = [ 1, 2, 3 ]
local $b[3] = [ 4, 5, 6 ]
local $c[2] = [ $a, $b ]

$a = 0 ; erase array $a
$b = 0 ; erase array $b

_ArrayDisplay($a) ; line won't execute as array $a has been erased
_ArrayDisplay($b) ; line won't execute as array $b has been erased

_ArrayDisplay($c, "Magic, $c still here !")
_ArrayDisplay($c[0], "$c[0] i'm here too !") ; display 1,2,3
_ArrayDisplay($c[1], "$c[1] alive & kicking !") ; display 4,5,6

 

Link to comment
Share on other sites

@Malkey : based on your examples, I found a way to simplify the _ASA function to 1 line only.
That was a great experimenting day :)

#include <Array.au3>

;  --------- Testing 1D array ----------
Local $b[] = [2, 3, 4], $a[4] = [1, $b, 5, 6]
_ArrayDisplay($a, "$a[4] = [1,$b,5,6]")

ConsoleWrite("($a[1])[1] = " & ($a[1])[1] & @CRLF)
_ASA($a[1], 1, 7)
ConsoleWrite("($a[1])[1] = " & ($a[1])[1] & @CRLF)

_ArrayDisplay($a[1], "3 to 7")

;  --------- Assign to Sub-Array (ASA) ---------
Func _ASA(ByRef $array, $iIndex, $Value)
    $array[$iIndex] = $Value ; Assign the new value.
EndFunc   ;==>_ASA

 

Link to comment
Share on other sites

11 hours ago, pixelsearch said:

@Malkey : based on your examples, I found a way to simplify the _ASA function to 1 line only.
That was a great experimenting day :)

#include <Array.au3>

;  --------- Testing 1D array ----------
Local $b[] = [2, 3, 4], $a[4] = [1, $b, 5, 6]
_ArrayDisplay($a, "$a[4] = [1,$b,5,6]")

ConsoleWrite("($a[1])[1] = " & ($a[1])[1] & @CRLF)
_ASA($a[1], 1, 7)
ConsoleWrite("($a[1])[1] = " & ($a[1])[1] & @CRLF)

_ArrayDisplay($a[1], "3 to 7")

;  --------- Assign to Sub-Array (ASA) ---------
Func _ASA(ByRef $array, $iIndex, $Value)
    $array[$iIndex] = $Value ; Assign the new value.
EndFunc   ;==>_ASA

 

Thanks pixelsearch,

This solution is the one I actually did implement to solve my problem.

I was though in the hope of a builtin way to do it, without the need of a function.

My problem is that I actually manage arrays of arrays of arrays of arrays... so I need to implement several _ASA variants, such as:

Func _ASA(ByRef $array, $i, $Value)
    $array[$i] = $Value ; Assign the new value.
EndFunc
Func _ASA2(ByRef $array, $i, $j, $Value)
    _ASA($array[$i], $j, $Value)        ; perform: ($array[$i])[$j] = $Value
EndFunc
Func _ASA3(ByRef $array, $i, $j, $k, $Value)
    _ASA2($array[$i], $j, $k, $Value)   ; perform: (($array[$i])[$j])[$k] = $Value
EndFunc
; and so on...

Which is quite annoying...

Anyway thanks for your answers, all.

Link to comment
Share on other sites

2 hours ago, SharpDressedMan said:

My problem is that I actually manage arrays of arrays of arrays of arrays

I think now is the perfect time to rethink your data design. Maybe multiple arrays, maybe a database ...... would avoid complex scripting and hence reduce the risk of hard to diagnose errors.
Just my 2 cents worth ;)

My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2022-02-19 - Version 1.6.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts
OutlookEX (2021-11-16 - Version 1.7.0.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX_GUI (2021-04-13 - Version 1.4.0.0) - Download
Outlook Tools (2019-07-22 - Version 0.6.0.0) - Download - General Help & Support - Wiki
PowerPoint (2021-08-31 - Version 1.5.0.0) - Download - General Help & Support - Example Scripts - Wiki
Task Scheduler (NEW 2022-07-28 - Version 1.6.0.1) - Download - General Help & Support - Wiki

Standard UDFs:
Excel - Example Scripts - Wiki
Word - Wiki

Tutorials:
ADO - Wiki
WebDriver - Wiki

 

Link to comment
Share on other sites

  • 3 weeks later...
On 21/11/2018 at 1:10 PM, water said:

I think now is the perfect time to rethink your data design. Maybe multiple arrays, maybe a database ...... would avoid complex scripting and hence reduce the risk of hard to diagnose errors.
Just my 2 cents worth ;)

Thanks for your comment Water. However, I really need arrays of arrays. It's a powerfull AutoIt feature and I see no reason to do without it.

Anyway, I made my own UDF to manage arrays of arrays easily, and my problem is now solved.

Thanks, anyway.

PS : for people interested, here is the code:

func VecSetVal(byref $aArray, $xVal, $iIndex, $iIndex2 = Default, $iIndex3 = Default, $iIndex4 = Default, $iIndex5 = Default)
    if ($iIndex2 <> Default) then   ; recurse on multiple indexes
        VecSetVal($aArray[$iIndex], $xVal, $iIndex2, $iIndex3, $iIndex4, $iIndex5)
    else
        $aArray[$iIndex] = $xVal
    endif
endfunc

 

Link to comment
Share on other sites

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...