Jump to content

Delete a row from a multidim'ed array


Recommended Posts

_ArrayDelete is barfing on my attempts to delete a row from a multidim'ed array.

What needs to be done to do this? Does anyone have a version of _ArrayDelete that works with these types of arrays? Does _arraydelete support multidim'ed array row deletions and I'm just calling it worng?

TIA

Edited by sshrum

Sean Shrum :: http://www.shrum.net

All my published AU3-based apps and utilities

'Make it idiot-proof, and someone will make a better idiot'

 

Link to comment
Share on other sites

_ArrayDelete is barfing on my attempts to delete a row from a multidim'ed array.

What needs to be done to do this?  Does anyone have a version of _ArrayDelete that works with these types of arrays? Does _arraydelete support multidim'ed array row deletions and I'm just calling it worng?

TIA

<{POST_SNAPBACK}>

Looking at the _ArrayDelete function, you can apply the same techinque to multi-dimensioned array. Just that instead of copying a single element as you move through the array, you'll need to loop through all the dimensions and copy those as well.

The challenge is that you will have to write a seperate copy routine for every number of dimenisions that you want to support (1 for 1d, 1 for 2d, 1 for 3d, etc). That is unless you want to use Eval(), which would be very slow.

Link to comment
Share on other sites

This is what I came up with...just works with 2d arrays (since that's all I need for now):

Func _ArrayDeleteRow(ByRef $avArray, $iElement)
    Local $iR = 0, $iC = 0, $iRows = 0, $iCols = 0
    
    If (Not IsArray($avArray)) Then
        SetError(1); not an array
        Return ""
    EndIf
    
    Local $iRows = UBound($avArray); Row count
    Local $iCols = UBound($avArray, 2); Column count
    
    If $iRows = 1 Then
        SetError(2); 1 row
        Return ""
    EndIf
    
    If $iElement < 0 or $iElement > ($iRows - 1) Then
        seterror(3); out of row bounds
        Return ""
    EndIf
    
    Local $avNewArray[$iRows - 1][$iCols]
    
    for $iR = 0 to $iRows - 2
        if $iR = $iElement then ContinueLoop
        for $iC = 0 to $iCols - 1
            $avNewArray[$iR][$iC] = $avArray[$iR][$iC]
        Next
    Next
    
    $avArray = $avNewArray
    
    SetError(0)
    Return 1
EndFunc ;==>_ArrayDeleteRow

I'll post this in Script and scraps too. Enjoy!

Edited by sshrum

Sean Shrum :: http://www.shrum.net

All my published AU3-based apps and utilities

'Make it idiot-proof, and someone will make a better idiot'

 

Link to comment
Share on other sites

I was just thinking.... :)

What if I creatd a copy of the array and ReDim'ed it.

Let's say I had a 2-d array of [1000][20]

Let's say the element to be removed was 200.

Couldn't I just redim the copy to [200][20] and then redim it back up to [999][20] and start processing there?

This would make it uber fast (I think) for deletions closer to the ubound.

Is my logic flawed here?

Granted I could rewrite this func to deal with single, 2, and 3d arrays but, eh. :evil:

Any thoughts :">

Sean Shrum :: http://www.shrum.net

All my published AU3-based apps and utilities

'Make it idiot-proof, and someone will make a better idiot'

 

Link to comment
Share on other sites

I was just thinking....  :)

What if I creatd a copy of the array and ReDim'ed it.

Let's say I had a 2-d array of [1000][20]

Let's say the element to be removed was 200.

Couldn't I just redim the copy to [200][20] and then redim it back up to [999][20] and start processing there?

This would make it uber fast (I think) for deletions closer to the ubound.

Is my logic flawed here?

Granted I could rewrite this func to deal with single, 2, and 3d arrays but, eh.  :evil:

Any thoughts  :">

<{POST_SNAPBACK}>

Good idea, but why redim it twice? I'd do this:

say you have an array $a[1000][20] and you want to remove the [201] line...

;first, shift all the values down by one
for $i = 201 to 999
    for $j = 1 to 200
        $a[$i][$j] = $a[$i + 1][$j]
    next
next
;now get rid of the last value
redim $a[999]

Also, in your original code, I would replace this:

If (Not IsArray($avArray)) Then

with this:

If Not UBound($avArray, 0) = 2 Then

Since you want to know that $avArray is an array, and also that it is 2-dimensional, this line will kill the 2 birds with 1 stone.

Link to comment
Share on other sites

Ok...how about this; should work for 1, 2 and 3 dimensional arrays:

Func _ArrayDeleteRow(ByRef $avArray, $iElement)
    Local $iR = 0, $iC = 0, $iD = 0, $iRows = 0, $iCols = 0, $iDepth = 0
    If (Not IsArray($avArray)) Then
        SetError(1); not an array
        Return ""
    EndIf
    
    Local $iDims = Ubound($avArray, 0); Dimensions
    Local $iRows = UBound($avArray); Row count
    if $iDims >= 2 then Local $iCols = UBound($avArray, 2); Column count
    if $iDims = 3 then Local $iDepth = UBound($avArray, 3); Depth count
        
    If $iRows = 1 Then
        SetError(2); 1 row
        Return ""
    EndIf
    If $iElement < 0 or $iElement > ($iRows - 1) Then
        seterror(3); out of row bounds
        Return ""
    EndIf
    
    Select
        case $iDims = 1; single dimension
            for $iR = $iElement + 1 to $iRows - 1
                $avArray[$iR-1] = $avArray[$iR]
            Next
            redim $avArray[$iRows-1]
        case $iDims = 2; 2d
            for $iR = $iElement + 1 to $iRows - 1
                for $iC = 0 to $iCols - 1
                    $avArray[$iR-1][$iC] = $avArray[$iR][$iC]
                Next
            next
            redim $avArray[$iRows-1][$iCols]
        case $iDims = 3; 3d
            for $iR = $iElement + 1 to $iRows - 1
                for $iC = 0 to $iCols - 1
                    for $iD = 0 to $iDepth - 1
                        $avArray[$iR-1][$iC][$iD] = $avArray[$iR][$iC][$iD]
                    Next
                Next
            next
            redim $avArray[$iRows-1][$iCols][$iDepth]
    EndSelect

    SetError(0)
    Return 1
EndFunc  ;==>_ArrayDeleteRow
Edited by sshrum

Sean Shrum :: http://www.shrum.net

All my published AU3-based apps and utilities

'Make it idiot-proof, and someone will make a better idiot'

 

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

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...