daten aus einem 2-D-Array vergleichen

  • hallo,

    ich habe ein script, mit dem ich über pixelsearch den Bildschrim nach bestimmten punkten absuche, all diese punkte werden anschließend in eine txt datei geschrieben, dann werden diese mit hilfe der Funktion _array2dsortfree von BugFix geordnet, nun möchte ich aber auch noch bestimmte Koordinaten aussortieren

    ( - für jedes Y der kleinste X-Wert
    - für jedes Y der größte X-Wert
    jetzt umsortieren X-aufsteigend und innerhalb von X die Y-Werte absteigend
    - für jedes X der kleinste Y-Wert
    - für jedes X der größte Y-Wert)

    wie kann ich das realisieren?

    MfG

    filewalker

    • Offizieller Beitrag

    Mal als Anregung, versuche es dann umzusetzen:
    - Gehe durch das Ergebnis-Array
    - Schreibe Wert 1 in ein Temporäres Array (hat jetzt kleinstes X)
    - Solange Y gleich ist tue nichts
    - Wenn Y den nächsten Wert annnimmt wird auch dieser Wert in Tmp-Array geschrieben
    - der vorhergehende Wert ist dann der letzte und somit mit größtem X für das vorige Y (auch in Tmp-Array schreiben)
    - der letzte Eintrag im Array ist auch der mit größtem X für das letzte Y
    so weiter bis zum Ende
    Analog vorgehen nach dem Umsortieren (des Ergebnisarray, nicht des Tmp-Array) für X und zugehörige Y

    Am Ende sind nur die größten und kleinsten Werte im Tmp-Array.

    Edit: Ich habs mal auf die Schnelle gemacht, ungetestet. Befehlszeile für Sortieren mußt du noch einfügen.

    Spoiler anzeigen
    [autoit]

    $aErgebnisse[100][2] ; Ergebnisse sortiert nach Y fallend, X steigend ; [n][0] = X, [n][1] = Y
    $aTmp[1][2] ; leer, zum Aufnehmen der begrenzenden Koordinaten

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

    $aTmp[0][0] = $aErgebnisse[0][0] ; vorbelegen mit erstem Eintrag
    $aTmp[0][1] = $aErgebnisse[0][1]

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

    For $i = 1 To UBound($aErgebnisse) -1
    If $aTmp[UBound($aTmp)-1][1] <> $aErgebnisse[$i][1] Then ; Y hat neuen Wert
    ReDim $aTmp[UBound($aTmp)+2][2]
    $aTmp[UBound($aTmp)-2][0] = $aErgebnisse[$i-1][0] ; vorhergehenden Wert als größten Wert übernehmem
    $aTmp[UBound($aTmp)-2][1] = $aErgebnisse[$i-1][1] ; falls nur einer ist der doppelt (min u. max) wird später gelöscht
    $aTmp[UBound($aTmp)-1][0] = $aErgebnisse[$i][0] ; aktueller Wert als neuer kleinster Wert
    $aTmp[UBound($aTmp)-1][1] = $aErgebnisse[$i][1]
    EndIf
    Next
    ReDim $aTmp[UBound($aTmp)+1][2]
    $aTmp[UBound($aTmp)-1][0] = $aErgebnisse[UBound($aErgebnisse)-1][0] ; letzter Wert ist letzter größter Wert
    $aTmp[UBound($aTmp)-1][1] = $aErgebnisse[UBound($aErgebnisse)-1][1]

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

    ;=========================================
    ; HIER NOCH DAS $aErgebnisse UMSORTIEREN!!
    ;=========================================

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

    ; jetzt mit umsortiertem Array alles wie gehabt aber für X
    ReDim $aTmp[UBound($aTmp)+1][2]
    $aTmp[UBound($aTmp)-1][0] = $aErgebnisse[0][0] ; vorbelegen mit erstem Eintrag
    $aTmp[UBound($aTmp)-1][1] = $aErgebnisse[0][1]

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

    For $i = 1 To UBound($aErgebnisse) -1
    If $aTmp[UBound($aTmp)-1][0] <> $aErgebnisse[$i][0] Then ; X hat neuen Wert
    ReDim $aTmp[UBound($aTmp)+2][2]
    $aTmp[UBound($aTmp)-2][0] = $aErgebnisse[$i-1][0] ; vorhergehenden Wert als größten Wert übernehmem
    $aTmp[UBound($aTmp)-2][1] = $aErgebnisse[$i-1][1] ; falls nur einer ist der doppelt (min u. max) wird später gelöscht
    $aTmp[UBound($aTmp)-1][0] = $aErgebnisse[$i][0] ; aktueller Wert als neuer kleinster Wert
    $aTmp[UBound($aTmp)-1][1] = $aErgebnisse[$i][1]
    EndIf
    Next
    ReDim $aTmp[UBound($aTmp)+1][2]
    $aTmp[UBound($aTmp)-1][0] = $aErgebnisse[UBound($aErgebnisse)-1][0] ; letzter Wert ist letzter größter Wert
    $aTmp[UBound($aTmp)-1][1] = $aErgebnisse[UBound($aErgebnisse)-1][1]

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

    ; jetzt doppelte Einträge entfernen
    _Array2DDblDel($aTmp)

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

    Func _Array2DDblDel(ByRef $ARRAY, $CASESENS=0)
    Local $arTmp[1] = [''], $dbl = 0, $count = 0, $x, $l, $val, $valTmp, $i, $k
    If ( Not IsArray($ARRAY) ) Then
    SetError(1)
    Return 0
    EndIf
    Local $Ubound2nd = UBound($ARRAY,2)
    If @error = 2 Then
    For $i = 0 To UBound($ARRAY)-1
    $dbl = 0
    For $k = 0 To UBound($arTmp)-1
    Switch $CASESENS
    Case 0
    If $arTmp[$k] = $ARRAY[$i] Then
    $dbl = 1
    $count += 1
    EndIf
    Case 1
    If $arTmp[$k] == $ARRAY[$i] Then
    $dbl = 1
    $count += 1
    EndIf
    EndSwitch
    Next
    If $dbl = 0 Then
    If $arTmp[0] = "" Then
    $arTmp[0] = $ARRAY[$i]
    Else
    ReDim $arTmp[UBound($arTmp)+1]
    $arTmp[UBound($arTmp)-1] = $ARRAY[$i]
    EndIf
    Else
    $dbl = 0
    EndIf
    Next
    Else
    ReDim $arTmp[1][$Ubound2nd]
    $arTmp[0][0] = ''
    $x = 0
    For $i = 0 To UBound($ARRAY)-1
    $dbl = 0
    $val = ''
    $valTmp = ''
    For $l = 0 To $Ubound2nd-1
    $val &= $ARRAY[$i][$l]
    Next
    For $k = 0 To UBound($arTmp)-1
    For $l = 0 To $Ubound2nd-1
    $valTmp &= $arTmp[$k][$l]
    Next
    Switch $CASESENS
    Case 0
    If $valTmp = $val Then
    $dbl = 1
    $count += 1
    EndIf
    Case 1
    If $valTmp == $val Then
    $dbl = 1
    $count += 1
    EndIf
    EndSwitch
    $valTmp = ''
    Next
    If $dbl = 0 Then
    If $x = 1 Then ReDim $arTmp[UBound($arTmp)+1][$Ubound2nd]
    For $l = 0 To $Ubound2nd-1
    If $arTmp[0][0] = '' Or $x = 0 Then
    $arTmp[0][$l] = $ARRAY[0][$l]
    If $l = $Ubound2nd-1 Then $x = 1
    Else
    $arTmp[UBound($arTmp)-1][$l] = $ARRAY[$i][$l]
    $x = 2
    If $l = $Ubound2nd-1 Then $x = 1
    EndIf
    Next
    Else
    $dbl = 0
    EndIf
    Next
    EndIf
    $ARRAY = $arTmp
    Return $count
    EndFunc ; ==>_Array2DDblDel

    [/autoit]
  • Vielen Dank BugFix. Ich habe jetzt aber ein Problem wenn ich die beiden codes zusammenfüge. Ich bkomme immer einen Fehler, dass $aErgebnisse nicht richtig deklariert wurde. Ich habe mal dan gesammten Code angehängt, habe schon einiges ausprobiert, habe jetzt aber nur das was mir am sinnvolsten erschien angehängt. Ich arbeite noch ncith so lange mit Autoit, deswegen kenne ich mich damit auch ncoh nciht sogut damit aus, aber heir wird einem ja bestens geholfen.

    Spoiler anzeigen
    [autoit]

    #cs ----------------------------------------------------------------------------
    AutoIt Version: 3.2.12.0
    Author: myName
    Script Function:
    Template AutoIt script.
    #ce ----------------------------------------------------------------------------
    ; Script Start - Add your code below here
    #include <SQLite.au3>
    #include <SQLite.dll.au3>
    Dim $DateiOut = @ScriptDir & "\Scanergebnis.txt"
    Dim $Farbe = 0x000000
    Dim $Schrittweite = 5
    _pix_scan($Farbe, $Schrittweite, $DateiOut)
    ;------------------------------------------------------------------------------------------------------------
    ; Funktion _pix_scan($color, $step, $file)
    ;
    ; Beschreibung scannt Display nach gesuchter Farbe, Ausgabe in Datei
    ; Pixelbereiche 2-stufig sortiert
    ;
    ; Parameter $color: zu suchende Farbe
    ; $step: Rastergröße
    ; $file: Ausgabedatei
    ;
    ; Return Datei mit den gefundenen Pixelpositionen
    ;
    ; Erfordernisse Funktion: _Array2DSortFree( )
    ; Nach dem Funktionsaufruf wird der Scan erst mit {F9} gestartet
    ; um z.B. vorab ein Spiel starten zu können
    ;
    ; Autor BugFix ([email='bugfix@autoit.de'][/email])
    ;------------------------------------------------------------------------------------------------------------
    #include <File.au3>
    #Include <Misc.au3>
    Func _pix_scan($color, $step, $file)
    Local $endX = @DesktopWidth, $endY = @DesktopHeight
    Local $left = 0, $top = 0, $right = $step, $bottom = $step
    Local $arPos, $arSort[1][1]
    Do
    Sleep(100)
    Until _IsPressed("78") ; F9
    $fh = FileOpen($file,1)
    Do
    For $left = 0 To $endX Step $step
    $pos = PixelSearch($left, $top, $right, $bottom, $color, 0, $step)
    If IsArray($pos) Then FileWriteLine($file, $pos[0] & "|" & $pos[1])
    $right += $step
    Next
    $left = 0
    $right = $step
    $top += $step
    $bottom += $step
    Until $bottom > $endY
    FileClose($fh)
    Beep(500, 2000)
    _FileReadToArray($file, $arPos)
    FileDelete($file)
    Dim $aErgebnisse[UBound($arPos)][2]
    For $i = 0 To UBound($arPos)-1
    $var = StringSplit($arPos[$i], "|")
    If ( IsArray($var) And UBound($var) = 3 ) Then
    $aErgebnisse[$i][0] = Number($var[1])
    $aErgebnisse[$i][1] = Number($var[2])
    EndIf
    Next
    _Array2DSortFree($aErgebnisse, '0|0,1|1')
    EndFunc

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

    For $i = 1 To UBound($aErgebnisse) -1
    If $aTmp[UBound($aTmp)-1][1] <> $aErgebnisse[$i][1] Then ; Y hat neuen Wert
    ReDim $aTmp[UBound($aTmp)+2][2]
    $aTmp[UBound($aTmp)-2][0] = $aErgebnisse[$i-1][0] ; vorhergehenden Wert als größten Wert übernehmem
    $aTmp[UBound($aTmp)-2][1] = $aErgebnisse[$i-1][1] ; falls nur einer ist der doppelt (min u. max) wird später gelöscht
    $aTmp[UBound($aTmp)-1][0] = $aErgebnisse[$i][0] ; aktueller Wert als neuer kleinster Wert
    $aTmp[UBound($aTmp)-1][1] = $aErgebnisse[$i][1]
    EndIf
    Next
    ReDim $aTmp[UBound($aTmp)+1][2]
    $aTmp[UBound($aTmp)-1][0] = $aErgebnisse[UBound($aErgebnisse)-1][0] ; letzter Wert ist letzter größter Wert
    $aTmp[UBound($aTmp)-1][1] = $aErgebnisse[UBound($aErgebnisse)-1][1]
    ;=========================================
    ; HIER NOCH DAS $aErgebnisse UMSORTIEREN!!
    ;=========================================
    _Array2DSortFree($aErgebnisse, '0|1,1|0')
    ; jetzt mit umsortiertem Array alles wie gehabt aber für X
    ReDim $aTmp[UBound($aTmp)+1][2]
    $aTmp[UBound($aTmp)-1][0] = $aErgebnisse[0][0] ; vorbelegen mit erstem Eintrag
    $aTmp[UBound($aTmp)-1][1] = $aErgebnisse[0][1]
    For $i = 1 To UBound($aErgebnisse) -1
    If $aTmp[UBound($aTmp)-1][0] <> $aErgebnisse[$i][0] Then ; X hat neuen Wert
    ReDim $aTmp[UBound($aTmp)+2][2]
    $aTmp[UBound($aTmp)-2][0] = $aErgebnisse[$i-1][0] ; vorhergehenden Wert als größten Wert übernehmem
    $aTmp[UBound($aTmp)-2][1] = $aErgebnisse[$i-1][1] ; falls nur einer ist der doppelt (min u. max) wird später gelöscht
    $aTmp[UBound($aTmp)-1][0] = $aErgebnisse[$i][0] ; aktueller Wert als neuer kleinster Wert
    $aTmp[UBound($aTmp)-1][1] = $aErgebnisse[$i][1]
    EndIf
    Next
    ReDim $aTmp[UBound($aTmp)+1][2]
    $aTmp[UBound($aTmp)-1][0] = $aErgebnisse[UBound($aErgebnisse)-1][0] ; letzter Wert ist letzter größter Wert
    $aTmp[UBound($aTmp)-1][1] = $aErgebnisse[UBound($aErgebnisse)-1][1]
    ; jetzt doppelte Einträge entfernen
    _Array2DDblDel($aTmp)

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

    $fh = FileOpen($file,1)
    For $i = 0 To UBound($aTmp)-1
    FileWriteLine($fh, $aTmp[$i][0] & $aTmp[$i][1] )
    Next
    FileClose($fh)
    Func _Array2DDblDel(ByRef $ARRAY, $CASESENS=0)
    Local $arTmp[1] = [''], $dbl = 0, $count = 0, $x, $l, $val, $valTmp, $i, $k
    If ( Not IsArray($ARRAY) ) Then
    SetError(1)
    Return 0
    EndIf
    Local $Ubound2nd = UBound($ARRAY,2)
    If @error = 2 Then
    For $i = 0 To UBound($ARRAY)-1
    $dbl = 0
    For $k = 0 To UBound($arTmp)-1
    Switch $CASESENS
    Case 0
    If $arTmp[$k] = $ARRAY[$i] Then
    $dbl = 1
    $count += 1
    EndIf
    Case 1
    If $arTmp[$k] == $ARRAY[$i] Then
    $dbl = 1
    $count += 1
    EndIf
    EndSwitch
    Next
    If $dbl = 0 Then
    If $arTmp[0] = "" Then
    $arTmp[0] = $ARRAY[$i]
    Else
    ReDim $arTmp[UBound($arTmp)+1]
    $arTmp[UBound($arTmp)-1] = $ARRAY[$i]
    EndIf
    Else
    $dbl = 0
    EndIf
    Next
    Else
    ReDim $arTmp[1][$Ubound2nd]
    $arTmp[0][0] = ''
    $x = 0
    For $i = 0 To UBound($ARRAY)-1
    $dbl = 0
    $val = ''
    $valTmp = ''
    For $l = 0 To $Ubound2nd-1
    $val &= $ARRAY[$i][$l]
    Next
    For $k = 0 To UBound($arTmp)-1
    For $l = 0 To $Ubound2nd-1
    $valTmp &= $arTmp[$k][$l]
    Next
    Switch $CASESENS
    Case 0
    If $valTmp = $val Then
    $dbl = 1
    $count += 1
    EndIf
    Case 1
    If $valTmp == $val Then
    $dbl = 1
    $count += 1
    EndIf
    EndSwitch
    $valTmp = ''
    Next
    If $dbl = 0 Then
    If $x = 1 Then ReDim $arTmp[UBound($arTmp)+1][$Ubound2nd]
    For $l = 0 To $Ubound2nd-1
    If $arTmp[0][0] = '' Or $x = 0 Then
    $arTmp[0][$l] = $ARRAY[0][$l]
    If $l = $Ubound2nd-1 Then $x = 1
    Else
    $arTmp[UBound($arTmp)-1][$l] = $ARRAY[$i][$l]
    $x = 2
    If $l = $Ubound2nd-1 Then $x = 1
    EndIf
    Next
    Else
    $dbl = 0
    EndIf
    Next
    EndIf
    $ARRAY = $arTmp
    Return $count
    EndFunc ; ==>_Array2DDblDel

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

    ;==================================================================================================
    ; Function Name: _Array2DSortFree($ARRAY, $sCOL_ASC)
    ; Description:: Sortierung von 1D/2D-Arrays nach freier Wahl
    ; 1D Sortierung Auf- oder Absteigend
    ; 2D mehrstufige Sortierung, Reihenfolge und Sortier-
    ; richtung (je Spalte) frei wählbar
    ; auch einzelne Spalte sortierbar
    ; Parameter(s): $ARRAY Das zu sortierende Array
    ; $sCOL_ASC String mit Sortierangaben "Spalte|Richtung [, Spalte|Richtung]"
    ; zu sortierende Spalte (0-Index)|Richtung (0-Asc, 1-Desc)
    ; z.B. Spalte 2 aufsteigend und in 2 absteigend Spalte 1
    ; _Array2DSortFree($ar2Sort, '2|0,1|1')
    ; Return Value(s): Erfolg 0
    ; Fehler 1 Set Error 1 $ARRAY ist kein Array
    ; 2 1D-Array, aber Spaltenangabe für 2D
    ; 3 SQL-Fehler
    ; 4 Angaben für Spalte|Sortierrichtung fehlerhaft
    ; Requirements: #include <SQLite.au3>
    ; #include <SQLite.dll.au3>
    ; Author(s): BugFix ([email='bugfix@autoit.de'][/email])
    ;==================================================================================================
    Func _Array2DSortFree(ByRef $ARRAY, $sCOL_ASC)
    If Not IsArray($ARRAY) Then Return SetError(1,0,1)
    Local $tableStr = "CREATE TABLE tblTEST ("
    Local $insertStr = '', $insertBase = "INSERT INTO tblTEST VALUES ("
    Local $sortOrder = '', $sortStr = "SELECT * FROM tblTEST ORDER BY "
    Local $aResult, $iRows, $iColumns, $iRval, $asc
    $sCOL_ASC = StringStripWS($sCOL_ASC, 8)
    Local $ub2nd = UBound($ARRAY, 2)
    If @error = 2 Then
    If (StringLen($sCOL_ASC) > 3) Or (StringLeft($sCOL_ASC, 1) <> '0') Then Return SetError(2,0,1)
    If StringRight($sCOL_ASC, 1) = 0 Then
    _ArraySort($ARRAY)
    Else
    _ArraySort($ARRAY, 1)
    EndIf
    Return 0
    Else
    Local $aOut[UBound($ARRAY)][$ub2nd]
    EndIf
    _SQLite_Startup ()
    If @error > 0 Then Return SetError(3,0,1)
    $hSQL = _SQLite_Open ()
    If @error > 0 Then
    _SQLite_Shutdown ()
    Return SetError(3,0,1)
    EndIf
    For $i = 0 To UBound($ARRAY, 2) -1
    $tableStr &= "'field" & $i & "',"
    Next
    $tableStr = StringTrimRight($tableStr, 1) & ");"
    For $i = 0 To UBound($ARRAY) -1 ; Erzeuge Insert-String
    $insertStr &= $insertBase
    For $k = 0 To UBound($ARRAY, 2) -1
    $insertStr &= "'" & $ARRAY[$i][$k] & "',"
    Next
    $insertStr = StringTrimRight($insertStr, 1) & ");"
    Next
    ; Erstelle Tabelle und füge Werte ein
    If _SQLite_Exec ( $hSQL, $tableStr & $insertStr ) <> $SQLITE_OK Then
    _SQLite_Shutdown ()
    Return SetError(3,0,1)
    EndIf
    If StringInStr($sCOL_ASC, ',') Then
    Local $aOrder = StringSplit($sCOL_ASC, ',')
    For $i = 1 To UBound($aOrder) -1
    If StringInStr($sCOL_ASC, '|') Then
    Local $var = StringSplit($aOrder[$i], '|')
    $asc = ' ASC'
    If $var[2] = 1 Then $asc = ' DESC'
    $sortOrder &= 'field' & $var[1] & $asc & ','
    Else
    _SQLite_Shutdown ()
    Return SetError(4,0,1)
    EndIf
    Next
    $sortOrder = StringTrimRight($sortOrder, 1) & ';'
    Else
    If (StringLen($sCOL_ASC) = 3) And (StringInStr($sCOL_ASC, '|')) Then
    Local $var = StringSplit($sCOL_ASC, '|')
    $asc = ' ASC'
    If $var[2] = 1 Then $asc = ' DESC'
    $sortOrder &= 'field' & $var[1] & $asc
    Else
    _SQLite_Shutdown ()
    Return SetError(4,0,1)
    EndIf
    EndIf
    $iRval = _SQLite_GetTable2d (-1, $sortStr & $sortOrder, $aResult, $iRows, $iColumns)
    If $iRval = $SQLITE_OK Then
    For $i = 1 To UBound($aResult) -1
    For $k = 0 To UBound($aResult,2) -1
    $aOut[$i-1][$k] = $aResult[$i][$k]
    Next
    Next
    Else
    _SQLite_Shutdown ()
    Return SetError(4,0,1)
    EndIf
    _SQLite_Exec ($hSQL, "DROP TABLE tblTEST;")
    _SQLite_Close ()
    _SQLite_Shutdown ()
    $ARRAY = $aOut
    Return 0
    EndFunc ;==> _Array2DSortFree

    [/autoit]
    • Offizieller Beitrag

    1. Du verwendest beim Scan Schrittweite 5. Ist das gewollt? Das bedeutet, dass aus einem 5x5 Pixel großen Raster nur die erste gefundene Koordinate zurückgegeben wird.

    2. Gib mir bitte mal die ganze Fehlermeldung, kopier sie aus der Commandline von SciTE. Hier in dem gezeigten Code ist nicht ersichtlich, wo eine fehlerhafte Deklaration sein soll. Kopier bitte den Verweis auf die Fehlerzeile und auch die entsprechende Zeile im Skript.

  • ok. diese fehlermeldung wird mir im Scite fenster angezeigt:


    falls gewünscht, kann ich dir auch genau sagen, was ich an deinem Script geändert habe.

    Gruß

    filewalker

    • Offizieller Beitrag

    Alle Fehlermeldungen beziehen sich darauf, dass die verwendeten Variablen z.B. erstmals innerhalb einer Funktion verwendet (somit als Local deklariert) werden und dann außerhalb der Funktion weitergenutzt werden sollen.
    Am Skriptanfang alle betroffenen Variablen als Global deklarieren.

  • danke, jetzt gehts.

    Jetzt hab ich nur noch nen Problem damit, die Werte in die Datei zu schreiben und dann in der richtigen reihenfolge.