Jump to content
Sign in to follow this  
JohnWPB

Help with "_ArrayInsert" with multi dimensional array

Recommended Posts

JohnWPB

Ok, I can not seem to figure out the syntax for the life of me on how to insert into an existing array, if the array has more than a single dimension / column.

I have tried variants that would seem to make "code sense" and can not seem to peg it down. Any help is greatly appreciated!

Here is a simple test script from the help file, altered a bit to make it 2 dimensional. If I can get it to insert in here, I can easily modify it for my script:

Thanks in advance for the help!

#include <Array.au3>
Local $NamesArray[10][10]

$NamesArray[0][0] = "Jim"
$NamesArray[0][1] = "test Jim"
$NamesArray[1][0] = "Frank"
$NamesArray[1][1] = "test Frank"
$NamesArray[2][0] = "John"
$NamesArray[2][1] = "test John"
$NamesArray[3][0] = "Larry"
$NamesArray[3][1] = "test Larry"

_ArrayDisplay($NamesArray, "$NamesArray BEFORE _ArrayInsert()")

;This is the single dimensional array insert from the help file:
_ArrayInsert($NamesArray, 2, "New")

;~ I am trying to insert it into the correct dimension / column
_ArrayInsert($NamesArray[2][1],"New")
;~ _ArrayInsert($NamesArray,[2][1], "New")

_ArrayDisplay($NamesArray, "$NamesArray AFTER _ArrayInsert()")

Share this post


Link to post
Share on other sites
smartee

Hi, :) _ArrayInsert only works with 1-dimensional arrays, you will have to address your array locations traditionally, just as you populated it in your script ;)

If you need any help again feel free to post back ;)

Share this post


Link to post
Share on other sites
JohnWPB

I had a feeling that was going to be the response :)

Ok, is there a workaround of any kind that someone can think of? Even if I can insert a single row, I can easily add the second column's values. I basically just need to bump everything else down the list at the insertion point.

EDIT: Thinking on this more, that wouldnt help, as the 2nd column would not be "bumped down" and the columns would be all out of sync, even if it could be done in some way)

I am trying to avoid:

Finding the spot to insert, reading before that into a new array with a for loop

finding the next line after it, and adding it to yet another array with a for loop

adding my new data to the end of the first array

then combining the two new array's back into sequence using another loop with ubound of the first loop, the second loop..........

Thats a lot of work, and not very clean code to say the least! Hahaha

Edited by JohnWPB

Share this post


Link to post
Share on other sites
smartee

Use Redim,:) it re-sizes the array, then just push everything down if needed.

Share this post


Link to post
Share on other sites
taietel

Here's a fast example (I've modified your array according to the values), with no error checking:

#include <Array.au3>
Local $NamesArray[10][2]

$NamesArray[0][0] = "Jim"
$NamesArray[0][1] = "test Jim"
$NamesArray[1][0] = "Frank"
$NamesArray[1][1] = "test Frank"
$NamesArray[2][0] = "John"
$NamesArray[2][1] = "test John"
$NamesArray[3][0] = "Larry"
$NamesArray[3][1] = "test Larry"

_ArrayDisplay($NamesArray, "$NamesArray BEFORE _ArrayInsert()")

;This is the single dimensional array insert from the help file:
;_ArrayInsert($NamesArray, 2, "New")

;~ I am trying to insert it into the correct dimension / column
;_ArrayInsert($NamesArray[2][1],"New")
;~ _ArrayInsert($NamesArray,[2][1], "New")
_InsertItem($NamesArray,"New,test New",2)

_ArrayDisplay($NamesArray, "$NamesArray AFTER _ArrayInsert()")

Func _InsertItem(ByRef $aArray, $sItem, $iPos)
 Local $sTmp
 $sTmp = StringSplit($sItem,",",2)

 Local $aTmp[UBound($aArray)+1][2]
 For $i=0 To $iPos-1
  $aTmp[$i][0]=$aArray[$i][0]
  $aTmp[$i][1]=$aArray[$i][1]
 Next
 $aTmp[$iPos][0]=$sTmp[0]
 $aTmp[$iPos][1]=$sTmp[1]
 For $i=$iPos+1 To UBound($aTmp)-1
  $aTmp[$i][0]=$aArray[$i-1][0]
  $aTmp[$i][1]=$aArray[$i-1][1]
 Next
 ReDim $aArray[UBound($aTmp)][2]
 $aArray = $aTmp
 Return $aArray
EndFunc

Share this post


Link to post
Share on other sites
JohnWPB

@Smartee Reading up on ReDim, seems similar to having to do the for loops and such, as it states when ReDim'd it must remain the same size or the data will be lost.

@taietel Wow, that's perfect! Uses the loops and such, but far cleaner than I could have pieced it together for sure :) Thanks much!

Share this post


Link to post
Share on other sites
smartee

@taietel: ;) Why didn't you just Redim and push down everything?

Your method copies over the entire array's contents, so that your use of Redim and Byref makes no sense. :) This will not scale well.

Byref exists to use the same variable and hence save copying over data when passing parameters, and Redim is there to save you from having to create a whole new array. :S

Share this post


Link to post
Share on other sites
taietel

@smartee, please elaborate "Why didn't you just Redim and push down everything?" because I don't understand. How can I do that?

Redim, at the last part of the function was indeed a surplus:

Func _InsertItem(ByRef $aArray, $sItem, $iPos)
 Local $sTmp
 $sTmp = StringSplit($sItem,",",2)
 Local $aTmp[UBound($aArray)+1][2]
 For $i=0 To UBound($aTmp)-1
  Switch $i
   Case 0 To $iPos-1
    $aTmp[$i][0]=$aArray[$i][0]
    $aTmp[$i][1]=$aArray[$i][1]
   Case $iPos
    $aTmp[$iPos][0]=$sTmp[0]
    $aTmp[$iPos][1]=$sTmp[1]
   Case Else
    $aTmp[$i][0]=$aArray[$i-1][0]
    $aTmp[$i][1]=$aArray[$i-1][1]
  EndSwitch
 Next
 $aArray = $aTmp
 Return $aArray
EndFunc

But why ByRef makes no sense?

Thanks in advance for your explanation!

Share this post


Link to post
Share on other sites
smartee

Ok sure :), hmm, when making functions that work with arrays, we must take care to not copy over elements except when absolutely necessary as this becomes very time consuming when working with large arrays.

Using Byref allows us to work directly with the original array, not a copy of the array as is the norm when passing parameters to functions. In your example you create another array then you copy this new array to the original one, thus defeating the purpose of using Byref to save us the time/memory associated with that copy operation. You may notice that your return statement is also not needed to retrieve your modified data when using Byref, for obvious reasons.

Here is an example of the simple Redim and push down I kept referring to :D

I was saving this to release with my coming soon ArrayEx.au3 UDF library, but now you get an exclusive preview :D

; #FUNCTION# ====================================================================================================================
; Name...........: _2DArrayInsertRow
; Description ...: Adds a row at the specified position of a 2D array.
; Syntax.........: _2DArrayInsertRow(ByRef $avArray, $iRow)
; Parameters ....: $avArray - Array to modify
;                  $iRow    - Position to insert row at
; Return values .: Success - New size of the first dimension of the array
;                  Failure - 0, sets @error
;                  |1 - $avArray is not an array
;                  |2 - $avArray is not a 2 dimensional array
; Author ........: smartee
; Modified.......:
; Remarks .......:
; Related .......: _ArrayInsert
; Link ..........;
; Example .......;
; ===============================================================================================================================
Func _2DArrayInsertRow(ByRef $avArray, $iRow)
    If Not IsArray($avArray) Then Return SetError(1, 0, 0)
    If UBound($avArray, 0) <> 2 Then Return SetError(2, 0, 0)

    ; Add 1 row to the array
    Local $iUBoundRow = UBound($avArray) + 1
    Local $iUBoundCol = UBound($avArray, 2)
    ReDim $avArray[$iUBoundRow][$iUBoundCol]

    ; Move all entries down until the specified position
    For $i = $iUBoundRow - 1 To $iRow + 1 Step -1
        For $j = 0 To $iUBoundCol - 1
            $avArray[$i][$j] = $avArray[$i - 1][$j]
        Next
    Next

    Return $iUBoundRow
EndFunc   ;==>_2DArrayInsertRow

And here is a simple example ;)

#include <Array.au3>
#include <ArrayEx.au3>

$avProcList = ProcessList() ; Retrieves a 2D array of the running processes 
_ArrayDisplay($avProcList, "Process list before _2DArrayInsertRow")

_2DArrayInsertRow($avProcList, 20)
$avProcList[0][0] += 1
$avProcList[20][0] = "HelloWorldProcess.exe"
$avProcList[20][1] = "43110"

_ArrayDisplay($avProcList, "Process list after _2DArrayInsertRow")

I hope this clears things up a bit for you taietel ;) Also, JohnWPB, feel free to incorporate this into your code :D

-smartee

Share this post


Link to post
Share on other sites
taietel

A BIG THANK YOU for the explanation! I have to study your example, especially the moving down part (I'm a little slow this time of night ;) ).

Regards,

taietel

[EDIT] GOT IT! I misunderstood the "moving down" words: I thought that the rows decrease their number, to the row that need to be inserted, instead increasing, hence the confusion.:)

Edited by taietel

Share this post


Link to post
Share on other sites
JohnWPB

very nice smartee! I already incorporated the code by taietel, so I will save yours to my "tool box" and use it in the future for sure!

I am not a programmer, and I usually muddly my way through what I am trying to do. I have it working now, and do not want to mess with it haha.

Luckily, this is something that will be used rarely, and only have about 20 items in the array, so not a big deal with memory & CPU ect.

Thanks for all the help guys!

Share this post


Link to post
Share on other sites
smartee

My pleasure :)

Share this post


Link to post
Share on other sites
wolf9228

Ok, I can not seem to figure out the syntax for the life of me on how to insert into an existing array, if the array has more than a single dimension / column.

I have tried variants that would seem to make "code sense" and can not seem to peg it down. Any help is greatly appreciated!

Here is a simple test script from the help file, altered a bit to make it 2 dimensional. If I can get it to insert in here, I can easily modify it for my script:

Thanks in advance for the help!

#include <Array.au3>
Local $NamesArray[10][10]

$NamesArray[0][0] = "Jim"
$NamesArray[0][1] = "test Jim"
$NamesArray[1][0] = "Frank"
$NamesArray[1][1] = "test Frank"
$NamesArray[2][0] = "John"
$NamesArray[2][1] = "test John"
$NamesArray[3][0] = "Larry"
$NamesArray[3][1] = "test Larry"

_ArrayDisplay($NamesArray, "$NamesArray BEFORE _ArrayInsert()")

;This is the single dimensional array insert from the help file:
_ArrayInsert($NamesArray, 2, "New")

;~ I am trying to insert it into the correct dimension / column
_ArrayInsert($NamesArray[2][1],"New")
;~ _ArrayInsert($NamesArray,[2][1], "New")

_ArrayDisplay($NamesArray, "$NamesArray AFTER _ArrayInsert()")

#include <Array.au3>

Dim $2DArray[6][6]
For $i = 0 To 5
For $j = 0 To 5
$2DArray[$i][$j] = " Value ( " &  $i & "|" & $J & " )"
Next
Next
_ArrayDisplay($2DArray, "New 2DArray")
ArrayInsert($2DArray,"Insert ( 3|3 )",6,6)
_ArrayDisplay($2DArray, "Insert 2DArray")

ReDim $2DArray[6][6]
For $i = 0 To 5
For $j = 0 To 5
$2DArray[$i][$j] = " Value ( " &  $i & "|" & $J & " )"
Next
Next
_ArrayDisplay($2DArray, "New 2DArray")
ArrayInsert($2DArray,"Insert ( 0|0 )",0,0)
_ArrayDisplay($2DArray, "Insert 2DArray")

ReDim $2DArray[6][6]
For $i = 0 To 5
For $j = 0 To 5
$2DArray[$i][$j] = " Value ( " &  $i & "|" & $J & " )"
Next
Next
_ArrayDisplay($2DArray, "New 2DArray")
ArrayInsert($2DArray,"Insert ( 8|8 )",8,8)
_ArrayDisplay($2DArray, "Insert 2DArray")


ReDim $2DArray[6][6]
For $i = 0 To 5
For $j = 0 To 5
$2DArray[$i][$j] = " Value ( " &  $i & "|" & $J & " )"
Next
Next
_ArrayDisplay($2DArray, "New 2DArray")
ArrayInsert($2DArray,"Insert ( 3|8 )",3,8)
_ArrayDisplay($2DArray, "Insert 2DArray")


ReDim $2DArray[6][6]
For $i = 0 To 5
For $j = 0 To 5
$2DArray[$i][$j] = " Value ( " &  $i & "|" & $J & " )"
Next
Next
_ArrayDisplay($2DArray, "New 2DArray")
ArrayInsert($2DArray,"Insert ( 8|3 )",8,3)
_ArrayDisplay($2DArray, "Insert 2DArray")


Dim $1DArray[6]
For $i = 0 To 5
$1DArray[$i] = " Value ( " &  $i & " )"
Next
_ArrayDisplay($1DArray, "1DArray")
ArrayInsert($1DArray,"Insert ( 3 )",3)
_ArrayDisplay($1DArray, "1DArray")

ReDim $1DArray[6]
For $i = 0 To 5
$1DArray[$i] = " Value ( " &  $i & " )"
Next
_ArrayDisplay($1DArray, "1DArray")
ArrayInsert($1DArray,"Insert ( 9 )",9)
_ArrayDisplay($1DArray, "1DArray")


Func ArrayInsert(ByRef $Array,$Value,$rowElement,$colElement = 0)
if $rowElement < 0 Or $colElement < 0 Then Return SetError(1,0,False)
Switch UBound($Array, 0)
Case 1
$rows = UBound($Array)
Select
Case ($rowElement > ($rows - 1))
ReDim $Array[$rowElement + 1]
$Array[$rowElement] = $Value
Return SetError(0,0,True)
Case Else
ReDim $Array[$rows + 1]
Local $TempArray[$rows + 1] , $R = 0
For $i = 0 To ($rows - 1)
if $i = $rowElement Then $R = 1
$TempArray[$i + $R] = $Array[$i]
Next
$TempArray[$rowElement] = $Value
$Array = $TempArray
Return SetError(0,0,True)
EndSelect
Case 2
$rows = UBound($Array)
$cols = UBound($Array, 2)
Select
Case ($rowElement > ($rows - 1)) Or ($colElement > ($cols - 1))
Select
Case ($rowElement > ($rows - 1)) And ($colElement > ($cols - 1))
ReDim $Array[$rowElement + 1][$colElement + 1]
$Array[$rowElement][$colElement] = $Value
Return SetError(0,0,True)
Case ($rowElement > ($rows - 1)) And ($colElement <= ($cols - 1))
ReDim $Array[$rowElement + 1][$cols + 1]
Local $TempArray[$rowElement + 1][$cols + 1] , $C
For $i = 0 To ($rowElement)
$C = 0
For $j = 0 To ($cols - 1)
if $j = $colElement Then $C = 1
$TempArray[$i][$j + $C] = $Array[$i][$j]
Next
Next
$TempArray[$rowElement][$colElement] = $Value
$Array = $TempArray
Return SetError(0,0,True)
Case ($rowElement <= ($rows - 1)) And ($colElement > ($cols - 1))
ReDim $Array[$rows + 1][$colElement + 1]
Local $TempArray[$rows + 1][$colElement + 1] , $R
For $j = 0 To $colElement
$R = 0
For $i = 0 To ($rows - 1)
if $i = $rowElement Then $R = 1
$TempArray[$i + $R][$j] = $Array[$i][$j]
Next
Next
$TempArray[$rowElement][$colElement] = $Value
$Array = $TempArray
Return SetError(0,0,True)
EndSelect
Case Else
ReDim $Array[$rows + 1][$cols + 1]
Local $TempArray[$rows + 1][$cols + 1]
Local $R , $C
For $j = 0 To ($cols - 1)
$C = 0
if $j >= $colElement Then $C = 1
For $i = 0 To ($rows - 1)
$R = 0
if $i >= $rowElement Then $R = 1
$TempArray[$i + $R][$j + $C] = $Array[$i][$j]
Next
Next
$TempArray[$rowElement][$colElement] = $Value
$Array = $TempArray
Return SetError(0,0,True)
EndSelect
Case Else
Return SetError(1,0,False)
EndSwitch
EndFunc
Edited by wolf9228

صرح السماء كان هنا

 

Share this post


Link to post
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
Sign in to follow this  

×

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.