Jump to content

Help with "_ArrayInsert" with multi dimensional array


Recommended Posts

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()")
Link to post
Share on other sites

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
Link to post
Share on other sites

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
Link to post
Share on other sites

@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!

Link to post
Share on other sites

@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

Link to post
Share on other sites

@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!

Link to post
Share on other sites

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

Link to post
Share on other sites

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
Link to post
Share on other sites

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!

Link to post
Share on other sites

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

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

 

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
  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...