Werte aus/in Sub-Array direkt lesen/schreiben

    • Offizieller Beitrag

    Edit 27.07.07 [alles gaaanz neu]

    Da AutoIt die Möglichkeit bietet, in einem Array als Elemente Arrays abzulegen, habe ich eine Funktion erstellt, die ein direktes Auslesen und auch Schreiben von Sub-Arrayelementen ermöglicht.

    In der aktualisierten Version sind nun bei Parent-Array und auch bei Sub-Array 2D-Arrays einsetzbar ohne Limitierung.

    _SubArray2DGetEntry($ARRAY, $SubRow, $ParentRow [, $SubCol=-1 [, $ParentCol=-1])

    _SubArray2DSetEntry($ARRAY, $Entry, $SubRow, $ParentRow [, $SubCol=-1 [, $ParentCol=-1])

    - $ARRAY ==> Ausgangsarray
    - $Entry ==> Nur bei ...SetEntry(), der zu setzende Wert
    - $SubRow ==> Zeilen-Index Sub-Array
    - $ParentRow ==> Zeilen-Index Parent-Array (enthält das Sub-Array
    - $SubCol=-1 ==> Spalten-Index Sub-Array, Standard ist -1 ==> nur 1D
    - $ParentCol=-1 ==> Spalten-Index Parent-Array, Standard ist -1 ==> nur 1D

    Das Bsp.ist auch aktualisiert:

    Spoiler anzeigen
    [autoit]

    Dim $ar1_1[3]=[0,1,2]
    Dim $ar1_2[3]=[3,4,5]
    Dim $ar1_3[3]=[6,7,8]
    Dim $ar1_4[3]=[9,10,11]
    Dim $ar1_5[3]=[12,13,14]

    [/autoit] [autoit][/autoit] [autoit]

    Dim $ar1[5]=[$ar1_1,$ar1_2,$ar1_3,$ar1_4,$ar1_5]

    [/autoit] [autoit][/autoit] [autoit]

    MsgBox(0, '$ar1[2] -> SubArray[1]', _SubArray2DGetEntry($ar1, 1, 2)) ; = $ar1_3[1] ==> 7
    _SubArray2DSetEntry($ar1, 77, 1, 2) ; Wert wird auf 77 geändert
    MsgBox(0, '$ar1[2] -> SubArray[1]; Wert geändert', _SubArray2DGetEntry($ar1, 1, 2)) ; geänderter Wert

    [/autoit] [autoit][/autoit] [autoit]

    Dim $ar2[5][3]
    $ar2[0][0] = $ar1_1
    $ar2[1][0] = $ar1_4
    $ar2[2][0] = $ar1_2
    $ar2[3][0] = $ar1_5
    $ar2[4][0] = $ar1_3

    [/autoit] [autoit][/autoit] [autoit]

    $ar2[0][1] = $ar1_2
    $ar2[1][1] = $ar1_1
    $ar2[2][1] = $ar1_3
    $ar2[3][1] = $ar1_4
    $ar2[4][1] = $ar1_5

    [/autoit] [autoit][/autoit] [autoit]

    $ar2[0][2] = $ar1_4
    $ar2[1][2] = $ar1_2
    $ar2[2][2] = $ar1_5
    $ar2[3][2] = $ar1_3
    $ar2[4][2] = $ar1_1

    [/autoit] [autoit][/autoit] [autoit]

    MsgBox(0, '$ar2[2][2] -> SubArray[1]', _SubArray2DGetEntry($ar2, 1, 2, -1, 2)) ; = $ar2[2][2] Idx 1 = $ar1_5[1] ==> 13
    _SubArray2DSetEntry($ar2, 133, 1, 2, -1, 2) ; Wert wird auf 133 geändert
    MsgBox(0, '$ar2[2][2] -> SubArray[1]; Wert geändert', _SubArray2DGetEntry($ar2, 1, 2, -1, 2)) ; geänderter Wert

    [/autoit] [autoit][/autoit] [autoit]

    Dim $ar3[2][2]
    $ar3[0][0] = 'eins'
    $ar3[1][0] = 'zwei'
    $ar3[0][1] = 'drei'
    $ar3[1][1] = 'vier'

    [/autoit] [autoit][/autoit] [autoit]

    $ar2[0][1] = $ar3 ; 2D-Array in 2D-Array

    [/autoit] [autoit][/autoit] [autoit]

    MsgBox(0, '$ar2[0][1] -> SubArray[0][1]', _SubArray2DGetEntry($ar2, 0, 0, 1, 1)) ; = $ar2[0][1] Sub[0][1] = $ar3[0][1] ==> 'drei'
    _SubArray2DSetEntry($ar2, 'dreißig', 0, 0, 1, 1) ; Wert wird auf 'dreißig' geändert
    MsgBox(0, '$ar2[0][1] -> SubArray[0][1]; Wert geändert', _SubArray2DGetEntry($ar2, 0, 0, 1, 1)) ; geänderter Wert

    [/autoit] [autoit][/autoit] [autoit]

    ;----------------------------------------------------------------------------------------------------------------------
    ; Function _SubArray2DGetEntry(ByRef $ARRAY, $SubRow, $ParentRow [, $SubCol=-1 [, $ParentCol=-1])
    ;
    ; Description For Array with Array as entry you got the determined entry
    ; Works with any occurences in 2nd Dimension (parent array and sub-array too)
    ; Works also with 1D-Array
    ;
    ; Parameter $ARRAY Given array with array as entrys
    ; $SubRow 0-based row -index of the entry inside the sub-array, you want to got
    ; $ParentRow 0-based row -index of parent-array
    ; optional $SubCol 0-based column -index of sub-array, (if exists)
    ; optional $ParentCol 0-based column -index of parent-array, (if exists)
    ;
    ; Return Succes value from determined sub-array
    ; Failure 0 and set @error
    ; @error = 1 given array is not array
    ; @error = 2 row -index for parent-array out of range
    ; @error = 3 col -index for parent-array out of range
    ; @error = 4 col -index for parent-array is given, but array is 1D
    ; @error = 5 row -index for sub-array out of range
    ; @error = 6 col -index for sub-array out of range
    ; @error = 7 col -index for sub-array is given, but array is 1D
    ;
    ; Author BugFix ([email='bugfix@autoit.de'][/email])
    ;----------------------------------------------------------------------------------------------------------------------
    Func _SubArray2DGetEntry(ByRef $ARRAY, $SubRow, $ParentRow, $SubCol=-1, $ParentCol=-1)
    If (Not IsArray($ARRAY)) Then
    SetError(1)
    Return 0
    EndIf
    If ($ParentRow < 0) Or ($ParentRow > UBound($ARRAY)-1) Then
    SetError(2)
    Return 0
    EndIf
    Local $Ub2ndParent = UBound($ARRAY, 2)
    If @error Then
    If $ParentCol <> -1 Then
    SetError(4)
    Return 0
    EndIf
    ElseIf ($ParentCol < -1) Or ($ParentCol > $Ub2ndParent-1) Then
    SetError(3)
    Return 0
    EndIf
    Switch $ParentCol
    Case -1
    Local $arSub = $ARRAY[$ParentRow]
    Case Else
    Local $arSub = $ARRAY[$ParentRow][$ParentCol]
    EndSwitch
    If ($SubRow < 0) Or ($SubRow > UBound($arSub)-1) Then
    SetError(5)
    Return 0
    EndIf
    Local $Ub2ndSub = UBound($arSub, 2)
    If @error Then
    If $SubCol <> -1 Then
    SetError(7)
    Return 0
    Else
    Return $arSub[$SubRow]
    EndIf
    Else
    If ($SubCol < 0) Or ($SubCol > $Ub2ndSub) Then
    SetError(6)
    Return 0
    Else
    Return $arSub[$SubRow][$SubCol]
    EndIf
    EndIf
    EndFunc ;==>_SubArray2DGetEntry

    [/autoit] [autoit][/autoit] [autoit]

    ;----------------------------------------------------------------------------------------------------------------------
    ; Function _SubArray2DSetEntry(ByRef $ARRAY, $Entry, $SubRow, $ParentRow [, $SubCol=-1 [, $ParentCol=-1])
    ;
    ; Description For Array with Array as entry you set the determined entry
    ; Works with any occurences in 2nd Dimension (parent array and sub-array too)
    ; Works also with 1D-Array
    ;
    ; Parameter $ARRAY Given array with array as entrys
    ; $Entry Value you want to set in the sub-array
    ; $SubRow 0-based row -index of the entry inside the sub-array, you want to set
    ; $ParentRow 0-based row -index of parent-array
    ; optional $SubCol 0-based column -index of sub-array, (if exists)
    ; optional $ParentCol 0-based column -index of parent-array, (if exists)
    ;
    ; Return Succes -1 value is set
    ; Failure 0 and set @error
    ; @error = 1 given array is not array
    ; @error = 2 row -index for parent-array out of range
    ; @error = 3 col -index for parent-array out of range
    ; @error = 4 col -index for parent-array is given, but array is 1D
    ; @error = 5 row -index for sub-array out of range
    ; @error = 6 col -index for sub-array out of range
    ; @error = 7 col -index for sub-array is given, but array is 1D
    ;
    ; Author BugFix ([email='bugfix@autoit.de'][/email])
    ;----------------------------------------------------------------------------------------------------------------------
    Func _SubArray2DSetEntry(ByRef $ARRAY, $Entry, $SubRow, $ParentRow, $SubCol=-1, $ParentCol=-1)
    If (Not IsArray($ARRAY)) Then
    SetError(1)
    Return 0
    EndIf
    If ($ParentRow < 0) Or ($ParentRow > UBound($ARRAY)-1) Then
    SetError(2)
    Return 0
    EndIf
    Local $Ub2ndParent = UBound($ARRAY, 2)
    If @error Then
    If $ParentCol <> -1 Then
    SetError(4)
    Return 0
    EndIf
    ElseIf ($ParentCol < -1) Or ($ParentCol > $Ub2ndParent-1) Then
    SetError(3)
    Return 0
    EndIf
    Switch $ParentCol
    Case -1
    Local $arSub = $ARRAY[$ParentRow]
    Case Else
    Local $arSub = $ARRAY[$ParentRow][$ParentCol]
    EndSwitch
    If ($SubRow < 0) Or ($SubRow > UBound($arSub)-1) Then
    SetError(5)
    Return 0
    EndIf
    Local $Ub2ndSub = UBound($arSub, 2)
    If @error Then
    If $SubCol <> -1 Then
    SetError(7)
    Return 0
    Else
    $arSub[$SubRow] = $Entry
    EndIf
    Else
    If ($SubCol < 0) Or ($SubCol > $Ub2ndSub) Then
    SetError(6)
    Return 0
    Else
    $arSub[$SubRow][$SubCol] = $Entry
    EndIf
    EndIf
    Switch $ParentCol
    Case -1
    $ARRAY[$ParentRow] = $arSub
    Case Else
    $ARRAY[$ParentRow][$ParentCol] = $arSub
    EndSwitch
    Return -1
    EndFunc ;==>_SubArray2DSetEntry

    [/autoit]
  • Zwischen Genie und wahnsinn ist bekanntlich nur ein schmaler Grad...


    Dein Avatar passt^^

    • Offizieller Beitrag

    HI,

    irgendwie reden wir aneinander vorbei. Ich hoffe mal, dass ich es nicht falsch verstehe. :D

    Also mal etwas ausführlicher:

    [autoit]

    MsgBox(0, '', _SubArrayGetEntry($ar2, 1, 2, 2)) ; = $ar2[2][2] Idx 1 = $ar1_5[1] ==> 13

    [/autoit]

    In dieser Zeile rufst du deine Funktion auf (UDF) und übergibst das Array names $ar2, richtig?

    Wenn du in deiner Funktionsdeklaration das ganze so schreibst :

    [autoit]


    Func _SubArrayGetEntry($ARRAY, $SubIdx, $iDim1, $iDim2=-1)

    [/autoit]

    dann wird das Array im Speicher (obwohl es bereits drin ist) kopiert und anschließend bearbeitet.

    Dies könntest du vermeiden, wenn du ByRef nutzt, dann wird ein Pointer auf die Speicheradresse übergeben und das Originalarray analysiert.

    Da du keine Zuweisungen innerhalb deiner Funktion machst, wird das Oridinalarray auch nicht manipuliert.

    Dies sollte gerade bei großen Arrays mit ByRef schneller sein und außerdem ist bei deiner Funktion (wenn ich es richtig verstanden habe) die Kopierfunktion unnötig.

    So long,

    Mega

    • Offizieller Beitrag
    Zitat

    irgendwie reden wir aneinander vorbei. Ich hoffe mal, dass ich es nicht falsch verstehe.

    Den Eindruck hatte ich auch :D - Vielleicht solltest du nicht immer so wortkarg sein ? :P

    Ich stimme dir völlig zu. :)
    Dann wäre es doch eigentlich sinnvoll, wenn in AutoIt-Funktionen die Parameter ohne besondere Kennzeichnung als ByRef betrachtet werden. Für die Mehrzahl der Parameter ist doch eine ByRef-Übergabe sinnvoll - oder? Ausnahmen könnte man dann mit ByVal festlegen (gibts halt in AutoIt nicht explizit, alle Argumente sind ja automatisch ByVal). Kann mich schwach an meine VB-Übungen erinnern, da mußte man das sowieso festlegen.