_ArraySearch()

  • Hi,

    ich habe ein zweidimensionales Array, in dem ich nach einem Wert suchen will.

    Als Beispiel habe ich 60 genommen. Obwohl 60 nicht im Array ist, wird die Zahl gefunden, an der Position -1...

    Suche ich z.B. nach 76 oder 67, werden diese Zahlen zwar gefunden, jedoch alle an Position 0. (Okay, das ist unwichtig. Ich möchte nur wissen, ob ein Wert gefunden wurde - die Position ist egal. Das ist trotzdem seltsam...)

    [autoit]

    #include <Array.au3>
    Global $array[2][6] = [[76, 67, 58, 57, 56, 55], [0, 0, 0, 0, 0, 0]]
    Global $search = 60

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

    Global $test = _ArraySearch($array, $search, 0, UBound($array, 1)-1)
    ConsoleWrite("Searching for " & $search & @CRLF)
    If @error Then
    ConsoleWrite("@error: " & @error & @CRLF)
    Else
    ConsoleWrite("FOUND at position " & $test & @CRLF)
    EndIf

    [/autoit]

    Kann mir da bitte jemand weiterhelfen?

    Was ich brauche: Eine einfache Suche im dynamischen 2-dimensionalen Array nach einer Zahl.

    3 Mal editiert, zuletzt von pete_gzome (8. Juni 2012 um 19:08)

  • Mit _ArraySearch() kriege ich das nach einigem probieren auch nicht hin.
    Hab ne andere Lösung (nicht ganz ausgetestet, ist ja aber auch schon spät...) ;)

    Spoiler anzeigen
    [autoit]


    #include <Array.au3>
    Global $array[2][6] = [[76, 67, 58, 57, 56, 55],[0, 0, 0, 0, 0, 0]]

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

    MsgBox(0, "", _Search(60))
    MsgBox(0, "", _Search(67))

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

    Func _Search($Wert)
    Local $i, $k, $found = False
    For $i = 0 To UBound($array, 0) - 1
    For $k = 0 To UBound($array, 1) - 1
    If $array[$i][$k] = $Wert Then Return (True)
    Next
    Next
    Return (False)
    EndFunc ;==>_Search

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

    MfG ThPfund

    "Es könnte alles so einfach sein..."

  • Was ich noch zu _ArraySearch() sagen wollte:

    Der ReturnCode ist laut Hilfebeschreibung so zu interpretieren
    $test >= 0 Position, an der Suchwert gefunden wurde
    $test -1 Fehler, siehe @error
    @error = 6 Wert nicht gefunden

    Du hast zum Debuggen mit dem ConsoleWrite() den richtigen Ansatz, allerdings wird von _ArraySearch() bei dieser und verschiedenen anderen Parameter-Konstellationen @error nicht gesetzt, insofern kommen wir da nicht weiter. Dazu müsste man einen Blick auf die Funktion _ArraySearch() im Include Array.au3 werfen, wie dort mit den Parametern umgegangen wird...

    MfG ThPfund

    "Es könnte alles so einfach sein..."

    Einmal editiert, zuletzt von ThPfund (8. Juni 2012 um 09:22)

  • Zu dem Grund warum dir kein @error angezeigt wird:
    @error wird nach jedem Funktionsaufruf neu gesetzt. Das heißt also @error bezieht sich immer auf die zuletzt aufgerufene Funktion.
    In deinem Fall fragst du das @error des folgenden Aufrufes ab:

    [autoit]

    ConsoleWrite("Searching for " & $search & @CRLF)

    [/autoit]


    Das @error von _Arraysearch ist zu diesem Zeitpunkt schon wieder verworfen.

  • Hab mir die Funktion _ArraySearch() jetzt mal genauer angeschaut.
    So wie ich das sehe, liefert sie - keine anderen Fehler vorausgesetzt - die Position in der 1. Dimension zurück.
    Beim 1-dim.Array entspricht dies dem tatsächlichen Index, wo sich der Wert befindet.
    Beim 2.dim. Array macht sie es auch so, auch wenn sich der Wert in der 2. Dimension befindet, da sie ja nur 1 Rückgabewert hat.

    D.h., in Deinem Beispiel mit [2][6] beginnt der Index mit 0, der Wert 58 z.B. befindet sich an [0][2], also ist der Rückgabewert 0. Falls nicht gefunden @error=6.

    Im zweiten Hilfebeispiel kann der Autor Zeile und Spalte schön ausgeben, da er ja die Spalte beim Suchen schon vorgibt...

    MfG ThPfund

    "Es könnte alles so einfach sein..."

  • Du musst aber auch alle Spalten durchsuchen.

    [autoit]

    #include <Array.au3>

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

    Global $iIndex
    Global $array[2][6] = [[76, 67, 58, 55, 56, 55], [0, 0, 0, 60, 0, 0]]
    Global $search = 60

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

    _ArrayDisplay($array)

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

    ConsoleWrite("Searching for " & $search & @CRLF)
    For $i = 0 To UBound($array, 2) - 1
    $iIndex = _ArraySearch($array, $search, 0, 0, 0, 0, 1, $i)
    $iCol = $i
    If Not @error Then ExitLoop
    Next

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

    If @error Then
    ConsoleWrite("@error: " & @error & @CRLF)
    Else
    ConsoleWrite("FOUND at position " & $iIndex & "x" & $iCol & @CRLF)
    EndIf

    [/autoit]

    2 Mal editiert, zuletzt von m-obi (8. Juni 2012 um 11:51)

  • @ m-obi
    Wird der 8.Parameter ($iSubItem) nicht angegeben, steht er standardmäßig auf -1.
    Und dann wird das ganze 2-dim. Array durchsucht, mit allen Spalten, s. Zeile 7.

    Spoiler anzeigen
    [autoit]


    Func _ArraySearch( ..., $iSubItem = -1)
    ...
    Case 2 ; 2D array search
    Local $iUBoundSub = UBound($avArray, 2) - 1
    If $iSubItem > $iUBoundSub Then $iSubItem = $iUBoundSub
    If $iSubItem < 0 Then
    ; will search for all Col
    $iSubItem = 0
    Else
    $iUBoundSub = $iSubItem
    EndIf
    ...

    [/autoit]


    Ich glaube, die Dokumentation sollte da noch etwas deutlicher werden. Werde gelegentlich mal was dazu schreiben.

    MfG ThPfund

    "Es könnte alles so einfach sein..."

  • So, ich melde mich mal zurück. Danke erst einmal für alle Antworten!

    Ich habe mich entschieden, den Code von m-obi aus Post #6 zu nehmen. Nach einigem Probieren funktioniert er anscheinend korrekt :P Danke für diesen Code.

    ThPfund, danke für dein Bemühen. Der Code aus Post #1 funktioniert leider nicht vollkommen fehlerfrei. Beispielsweise liefert 55 trotz Vorhandensein im Array ein False.

    Danke noch einmal an alle!

  • Hier der Vollständigkeit halber noch meine korrigierte Funktion. Ursache war falsche Parameterangabe im Ubound (und späte Uhrzeit) ;)

    Spoiler anzeigen
    [autoit]


    #include <Array.au3>
    Global $array[2][6] = [[76, 67, 58, 57, 56, 55],[0, 0, 0, 0, 0, 0]]

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

    MsgBox(0, "76", _MySearch(76)) ; => True
    MsgBox(0, "60", _MySearch(60)) ; => False
    MsgBox(0, "55", _MySearch(55)) ; => True
    MsgBox(0, " 0", _MySearch(0)) ; => True

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

    Func _MySearch($Wert)
    Local $i, $k
    For $i = 0 To UBound($array, 1) - 1
    For $k = 0 To UBound($array, 2) - 1
    If $array[$i][$k] = $Wert Then Return (True)
    Next
    Next
    Return (False)
    EndFunc ;==>_MySearch

    [/autoit]

    MfG ThPfund

    "Es könnte alles so einfach sein..."

  • Hey super, dankeschön.

    Dann benutze ich doch die Version. Zudem brauche ich auch kein include :)

  • Hey super, dankeschön.

    Dann benutze ich doch die Version. Zudem brauche ich auch kein include :)

    Die Problematik an der Funktion von ThPfund ist, daß hier beim Aufruf kein zu durchsuchendes Array definiert werden kann.
    Desweiteren ist bei seiner Funktion ein 2-Dimensionales Array von Nöten.
    Ich habe das hier mal modifiziert:

    Spoiler anzeigen
    [autoit]

    #include <Array.au3>

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

    Global $array[2][6] = [[76, 67, 58, 57, 56, 55],[0, 0, 0, 0, 0, 0]]
    Global $array2[6] = [76, 67, 58, 57, 56, 55]

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

    MsgBox(0, "76", _MySearch($array, 76)) ; => True
    MsgBox(0, "60", _MySearch($array, 60)) ; => False
    MsgBox(0, "55", _MySearch($array, 55)) ; => True
    MsgBox(0, " 0", _MySearch($array, 0)) ; => True

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

    MsgBox(0, "76", _MySearch($array2, 76)) ; => True
    MsgBox(0, "60", _MySearch($array2, 60)) ; => False
    MsgBox(0, "55", _MySearch($array2, 55)) ; => True
    MsgBox(0, " 0", _MySearch($array2, 0)) ; => False

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

    Func _MySearch($SearchArray, $Wert)
    Local $i, $k
    For $i = 0 To UBound($SearchArray, 1) - 1
    If UBound($SearchArray, 0) = 2 Then
    For $k = 0 To UBound($SearchArray, 2) - 1
    If $SearchArray[$i][$k] = $Wert Then Return True
    Next
    Else
    If $SearchArray[$i] = $Wert Then Return True
    EndIf
    Next
    Return False
    EndFunc ;==>_MySearch

    [/autoit]
    UNPLEASANT SPOILER

    You just lost the game!

  • Sorry, mein Fehler: Ich hätte dazuschreiben sollen, dass ich nur eine der zwei Dimensionen (die erste) des Arrays durchsuchen will.

    Welchen Lösungsvorschlag soll ich jetzt nehmen?

    Edit:
    Ich benutze jetzt folgenden Code:

    [autoit]

    Global $array[2][6] = [[76, 67, 58, 57, 56, 55],[0, 0, 0, 0, 0, 0]]

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

    MsgBox(0, "76", _search($array, 76))
    MsgBox(0, "75", _search($array, 75))
    MsgBox(0, "68", _search($array, 68))
    MsgBox(0, "67", _search($array, 67))
    MsgBox(0, "60", _search($array, 60))
    MsgBox(0, "55", _search($array, 55))
    MsgBox(0, " 1", _search($array, 1))
    MsgBox(0, " 0", _search($array, 0))
    MsgBox(0, " 20", _search($array, 20))
    MsgBox(0, " 56", _search($array, 56))

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

    Func _search($searchArray, $value)
    Local $i
    For $i = 0 To UBound($searchArray, 2) - 1
    If $searchArray[0][$i] = $value Then Return True
    Next
    Return False
    EndFunc

    [/autoit]

    Bei allen Werten kommt das erwartete Ergebnis heraus. Entdeckt noch jemand einen Fehler? :P

    2 Mal editiert, zuletzt von pete_gzome (8. Juni 2012 um 17:52)

  • Das ist jetzt wohl richtig so. Und: Ja, klar meine Funktion ist ein Vorschlag, den man bedarfsgerecht anpassen kann.
    Ich habe aber noch Zweifel an der Gesamtkonstruktion. Bloß noch mal zum gemeinsamen Verständnis mit den Dimensionen:
    $array[1.Dim.][2.Dim.]
    $array[Zeilen][Spalten]
    $array[2][6] = [[76, 67, 58, 57, 56, 55],[0, 0, 0, 0, 0, 0]]
    Ergebnis ArrayDisplay:
    [0] | 76 | 67 | 58 | 57 | 56 | 55
    [1] | 0 | 0 | 0 | 0 | 0 | 0
    Dies ist bestimmt ein vereinfachtes Beispiel.
    Ist es in der Original-Anwendung wirklich beabsichtigt, nur die erste Zeile zu durchsuchen?

    MfG ThPfund

    "Es könnte alles so einfach sein..."

  • Ja, ich brauche für dieses Vorhaben nur die erste Dimension.

    Die zweite hat hiermit erst einmal nicht viel zu tun, die brauche ich für etwas anderes und habe sie der Einfachheit und Übersichtlichkeit halber mit in das Array gepackt.

    Einmal editiert, zuletzt von pete_gzome (8. Juni 2012 um 19:08)

  • Die erste Dimension ist die erste Spalte also 76 und 0.

    Nein, der Eintrag in der zweiten Dimension bestimmt die Spaltenzahl. Und ihr Index benennt dann die konkrete Spalte.
    Schau mal an, wie sich der Aufbau in _ArrayDisplay() verändert , wenn Du nacheinander folgende Arrays betrachtest:

    Spoiler anzeigen
    [autoit]


    #include <Array.au3>

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

    Local $array[2][1] ; [ersteDim][zweiteDim]
    _ArrayDisplay($array)
    ReDim $array[2][2]
    _ArrayDisplay($array)
    ReDim $array[2][3]
    _ArrayDisplay($array)
    ReDim $array[2][4]
    _ArrayDisplay($array)
    ReDim $array[2][5]
    _ArrayDisplay($array)
    ReDim $array[2][6]
    _ArrayDisplay($array)

    [/autoit]

    MfG ThPfund

    "Es könnte alles so einfach sein..."

  • Du hast es gesagt, der zweite Eintrag bestimmt die zweite Dimension. Da er aber nur die erste auslesen will, kommt nur die erste Spalte in Betracht. Aber er will ja irgendwie eher die komplette erste Zeile auslesen, also muss er in die zweite Dimension gehen.
    Den Aufbau eines Arrays hab ich schon verstanden ;).

    Er denkt die zweite Dim. ist die zweite Zeile. Die zweite Dim. ist aber ab Spalte 2 nach rechts.

  • Nochwas, wenn man bei _ArraySearch -1 eingibt, sucht er zwar in allen Spalten, aber du bekommst dann nur den Index zurück und nicht die Spalte wo es gefunden wurde, da er aber nur die erste Zeile durchsuchen will, bekommt er immer 0 wenn was gefunden wird. Deswegen hab ich _ArraySearch in eine Schleife gepackt, damit er die Spalten durchgeht und man dann auch weiß in welcher Spalte es gefunden wurde.

    Spoiler anzeigen
    [autoit]

    #include <Array.au3>

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

    Global $iIndex
    Global $array[2][6] = [[76, 67, 58, 55, 56, 55], [0, 0, 0, 60, 0, 0]]
    Global $search = 60

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

    _ArrayDisplay($array)

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

    ConsoleWrite("Searching for " & $search & @CRLF)
    For $i = 0 To UBound($array, 2) - 1
    $iIndex = _ArraySearch($array, $search, 0, 0, 0, 0, 1, $i)
    $iCol = $i
    If Not @error Then ExitLoop
    Next

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

    If @error Then
    ConsoleWrite("@error: " & @error & @CRLF)
    Else
    ConsoleWrite("FOUND at position " & $iIndex & "x" & $iCol & @CRLF)
    EndIf

    [/autoit]
  • Zu #17
    Gut, dann sind wir uns doch irgendwie über Dimensionen, Indexe, Zeilen und Spalten einig und dass die Werte $array[0][0 bis 5] des Beispiels gebraucht werden.

    Zu #18
    Ja. Gefragt war zunächst nur, ob der Wert im Array enthalten ist. Den Charme Deiner Lösung habe ich aber auch erkannt und sie bereits in meine Snippet-Sammlung übernommen. :thumbup:

    So ich klinke mich jetzt aus diesem Thread aus, bedanke mich für die engagierte Diskussion und wünsche allen noch ein schönes Wochende. :)

    MfG ThPfund

    "Es könnte alles so einfach sein..."

  • Achso ich dachte er wollte auch wissen wo es genau gefunden wurde. Dann ist ja jetzt alles geklärt.
    [Discussion closed]