Sign in to follow this  
Followers 0
mvk25

ArrayDeleteIndices

1 post in this topic

I was trying to write a function to delete specific elements from an array using their indices and found a function made by Bowmore here .

I modified the function to take an array of indices as input and to support 0-based and 1-based arrays.

Here is the function along with an example:

#AutoIt3Wrapper_Au3Check_Parameters=-q -d -w 1 -w 2 -w 3 -w- 4 -w 5 -w 6 -w- 7
#include <array.au3>

; #FUNCTION# ====================================================================================================================
; Name...........: _ArrayDeleteIndices
; Description ...: This function is passed an array with the indices of the elements that need to be deleted from a given 1 or 2
;                  dimensional array. The elements are deleted and the remaining elements are shifted up to take the empty spaces
; Syntax.........: _ArrayDeleteIndices(ByRef $avArray, Byref $aiIndices[, $iBase = Default])
; Parameters ....: $$avArray    - The 1 or 2 dimensional array to delete elements from
;                  $aiIndices   - The 1 dimensional array containing the indices of elements to delete
;                  $iBase       - If true then the arrays will be treated as 1 based. Default is 0
; Return values .: Success      - Returns 1
;                  Failure      - Returns 0 and sets @error to a non zero value
;                  @error       1 - If first parameter is not an array or an empty array
;                               2 - If Indices parameter is not an array or an empty array
;                               3 - If data array has more than 2 dimensions
;                               4 - If indices array starts with a non integer value or -ve value
;                               5 - $iBase is invalid
;                               6 - Element 0 is in indices array but the array is 1-based!
; Author ........: (mvk25) ... Based on _ArrayRemoveBlanks by (Bowmore)
;                  [autoitscript.com/forum/topic/132027-array-delete-blank-element/?p=919764]
; Modified.......:
; Remarks .......: Relies on _ArraySort and _ArrayUnique from array.au3 UDF
;
; Related .......: _ArrayDelete
; Link ..........:
; Example .......: Yes
; ===============================================================================================================================
Func _ArrayDeleteIndices(ByRef $avArray, ByRef $aiIndicesUnsrtd, $iBase = Default)
    ; Make sure $iBase is either 1 or 0
    If $iBase = Default Then $iBase = 0
    If $iBase < 0 Or $iBase > 1 Or (Not IsInt($iBase)) Then Return SetError(5, 0, 0)
    ; Check array parameters
    Local $aiArraySize[2] = [UBound($avArray)]
    If $aiArraySize[0] = $iBase Then Return SetError(1, 0, 0)
    If UBound($aiIndicesUnsrtd) = $iBase Then Return SetError(2, 0, 0)
    ; Get number of dimensions in data array and if more than 2 throw an error
    Local $iDims = UBound($avArray, 0)
    If $iDims > 2 Then Return SetError(3, 0, 0)

    ; Remove duplicate elements from the indices array
    Local $iColumn = 1, $iCase = 1, $iCountIn0Index = $iBase
    Local $aiIndices = _ArrayUnique($aiIndicesUnsrtd, $iColumn, $iBase, $iCase, $iCountIn0Index)
    ; Sort it ascendingly
    Local $iDescending = 0, $iSortStart = $iBase
    _ArraySort($aiIndices, $iDescending, $iSortStart)

    ; Check if array has a non integer or -ve element as first base element and return error
    If (Not IsInt($aiIndices[$iBase])) Or ($aiIndices[$iBase] < 0) Then Return SetError(4, 0, 0)
    ; Check if first base element is 0 when $iBase = 1 and return error
    If $iBase And $aiIndices[1] = 0 Then Return SetError(6, 0, 0)

    Local $iIndicesCount = UBound($aiIndices)
    Local $iIndex = $iBase
    Local $iIndexDel = $iBase
    $aiArraySize[1] = UBound($avArray, 2)
    For $i = $iBase To ($aiArraySize[0] - 1)
        If $i <> $aiIndices[$iIndexDel] Then
            For $j = 0 To ($aiArraySize[1] - 1)
                $avArray[$iIndex][$j] = $avArray[$i][$j]
            Next
            $iIndex += 1
        Else
            If $iIndexDel < ($iIndicesCount - 1) Then $iIndexDel += 1
        EndIf
    Next
    ReDim $avArray[$iIndex][$aiArraySize[1]]

    Return 1
EndFunc   ;==>_ArrayDeleteIndices

Example()

Func Example()
    Local $iBase = 0 ; Make the test array 0 based or 1 based
    Local $iElements = 13 ; Number of elements in test array
    Local $iDims = 2 ; Number of columns in test array

    ; Create the array
    Local $aArray[$iElements + $iBase][$iDims]
    ; Fill the array with characters starting from A
    For $i = $iBase To ($iElements + $iBase - 1)
        For $j = 0 To ($iDims - 1)
            $aArray[$i][$j] = Chr(65 + $i - $iBase + $j)
        Next
    Next

    ; Now create the array containing the indices to be deleted from test array
    Local $iCase = 1 ; Try different arrays
    Switch $iCase
        Case 1
            Local $aDel[] = [1, 3, 4, 11]
        Case 2
            Local $aDel[] = [10, 5, 3, 2, 0] ; Order is not important
        Case 3
            Local $aDel[] = [0, 5, 5, 1, 9, 9] ; Duplicate items are ignored
        Case 4
            Local $aDel[] = [999, 0, 1000000] ; Items outside range are ignored
        Case 5
            Local $aDel[] = [0, 10, -2]
        Case 6
            Local $aDel[] = [3, 5, 6, 0] ; Try this with $iBase = 1
        Case 7
            Local $aDel[5]
    EndSwitch

    _ArrayDisplay($aArray, "Before")
    _ArrayDeleteIndices($aArray, $aDel, $iBase)
    If @error Then
        ConsoleWrite("!Error Code: " & @error & @LF & @LF)
    Else
        _ArrayDisplay($aArray, "After")
    EndIf
EndFunc   ;==>Example

I need some feedback regarding the support 1-based arrays.

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  
Followers 0