Schlanke und schnelle Überprüfung eines Wertes

  • Hi,

    habe mal wieder eine eher kosmetische Frage (ich bin ja immer darauf erpicht, Code so schlank wie möglich und dabei effizient zu halten):
    WIe bekomme ich folgende Überprüfung eleganter hin (wenn es überhaupt eine Möglichkeit gibt)?

    [autoit]

    Local Const $I_MODE = 131
    If $I_MODE <> 1 And $I_MODE <> 2 And $I_MODE <> 9 And $I_MODE <> 10 And $I_MODE <> 17 And $I_MODE <> 18 And $I_MODE <> 25 And $I_MODE <> 26 And _
    $I_MODE <> 33 And $I_MODE <> 34 And $I_MODE <> 41 And $I_MODE <> 42 And $I_MODE <> 65 And $I_MODE <> 66 And $I_MODE <> 72 And _
    $I_MODE <> 74 And $I_MODE <> 129 And $I_MODE <> 130 And $I_MODE <> 137 And $I_MODE <> 138 Then Return SetError(5, 0, 0)

    [/autoit]

    Schon mal danke im voraus!

    PS: Ich habe letztens mal in den Foreneinstellungen rumgespielt und mein Design auf das Standard BB3 geändert. Nun wollte ich wieder zum AutoIt-Design zurück, muss aber feststellen, dass bei jeder neuen Anmeldung wieder das Standard BB3 Design ausgewählt wird. Kann das bitte jemand fixen? (Falls bereits geschehen bitte ignorieren!)

    Einmal editiert, zuletzt von teh_hahn (14. Februar 2008 um 22:00)

  • [autoit]

    Local Const $I_MODE = 131
    Dim $aArray[20] = [1, 2, 9, 10, 17, 18, 25, 26, 33 ,34, 41, 42, 65, 66, 72, 74, 129, 130, 137, 138]
    For $i = 0 To 20
    If $I_MODE <> $aArray[$i] Then Return SetError(5, 0, 0)
    Next

    [/autoit]

    so 8| ka

  • Das ist aber nicht das selbe.
    Teh hahn´s Code sagt aus das ein Error kommt wenn $I_MODE keinem der angegebenen Werte entspricht.
    Bei deinem hingegen wird immer ein Error zurückgeben - nämlich immer dann wenn ein Element kommt was nicht gleich $I_MODE entspricht.

    Ich hab´s spontan mal so gemacht:

    [autoit]

    Local Const $I_MODE = 131
    Local $NOTS[20] = [1,2,9,10,17,18,25,26,33,34,41,42,65,66,72,74,129,130,137,138]
    Local $Yes = 0
    For $i In $NOTS
    If $I_MODE = $i Then
    $Yes = 1
    ExitLoop
    EndIf
    Next
    If Not $Yes Then Return SetError(5, 0, 0)

    [/autoit]

    Oder so:

    [autoit]

    #include <array.au3>
    Local Const $I_MODE = 131
    Local $NOTS[20] = [1,2,9,10,17,18,25,26,33,34,41,42,65,66,72,74,129,130,137,138]
    If _ArraySearch($NOTS, $I_MODE) = -1 Then Return SetError(5, 0, 0)

    [/autoit]


    </array.au3>

    Einmal editiert, zuletzt von AspirinJunkie (14. Februar 2008 um 21:01)

  • Habe da auch so etwas, wo ich nicht weiss wie ich das verschönere ;)

    [autoit]


    if $hm = Filereadline("C:\blubb.txt", 1) then
    _lol()
    ElseIf $hm = Filereadline("C:\blubb.txt", 2) then
    _lol()
    ElseIf $hm = Filereadline("C:\blubb.txt", 3) then
    _lol()
    ElseIf $hm = Filereadline("C:\blubb.txt", 4) then
    _lol()
    Endif

    [/autoit]

    Kann mir das mal einer kurz vereinfachen? ^^

  • Ok, danke für die Hinweise, auf die Sache mit dem Array bin ich auch schon von alleine gekommen. Denke aber mal, dass das wohl insgesamt langsamer sein dürfte. (in diesem Beispiel natürlich relativ egal!):

    [autoit]

    Local $ai_ok[20] = [1, 2, 9, 10, 17, 18, 25, 26, 33, 34, 41, 42, 65, 66, 72, 74, 129, 130, 137, 138]
    Local $i_err = 1
    For $i = 0 To 19
    If $ai_ok[$i] = $I_MODE Then
    $i_err = 0
    ExitLoop
    EndIf
    Next
    If $i_err Then Return SetError(6, 0, 0)

    [/autoit]


    ergibt 248 Bytes Code - Zweiter!

    Oscars Ansatz fand ich sehr interessant, er war jedoch unsauber umgesetzt, da ja z.B. die 3 auch in 132 vorkommt. Ich habe daraus mal folgendes gebaut:

    [autoit]

    If Not StringInStr("|1|2|9|10|17|18|25|26|33|34|41|42|65|66|72|74|129|130|137|138|", "|" & $I_MODE & "|") Then Return SetError(6, 0, 0)

    [/autoit]


    ergibt 135 Bytes Code - Erster!

    Mein erstes Beispiel:

    [autoit]

    If $I_MODE <> 1 And $I_MODE <> 2 And $I_MODE <> 9 And $I_MODE <> 10 And $I_MODE <> 17 And $I_MODE <> 18 And $I_MODE <> 25 And $I_MODE <> 26 And _ $I_MODE <> 33 And $I_MODE <> 34 And $I_MODE <> 41 And $I_MODE <> 42 And $I_MODE <> 65 And $I_MODE <> 66 And $I_MODE <> 72 And _ $I_MODE <> 74 And $I_MODE <> 129 And $I_MODE <> 130 And $I_MODE <> 137 And $I_MODE <> 138 Then Return SetError(6, 0, 0)

    [/autoit]


    ergibt 399 Bytes Code - Dritter!

    Würde man nun noch die Variable auf ein Zeichen kürzen, wären das 299 Bytes Code. Nennt es Haarspalterei, aber zum Test hab ich es mal durch eine große Anzahl von Durchläufen mit einem Timer geschickt:

    Spoiler anzeigen
    [autoit]

    ;===============================================================================
    ; Function Name.....: _ArrayAverage
    ; Description.......: Returns the average of all values held in an array.
    ; Version...........: 1.0.1
    ; Change Date.......: 2008-02-05
    ; AutoIt Version....: 3.2.10.0
    ;
    ; Parameter(s)......: $AV_ARRAY - The array to scan.
    ; $I_START - [optional] Integer specifying the array index to start with (default = 0).
    ; $i_end - [optional] Integer specifying the array index to end with (default = 0, for the upper bound of the array).
    ; Requirements(s)...: None
    ; Return Value(s)...: Success: Returns a numeric value containing the average of all values held in the array.
    ; Failure: Returns 0 and sets @error to:
    ; 1 = $I_START is higher than $i_end.
    ; 2 = $I_START exceeds the upper bound of the array.
    ; 3 = $i_end index exceeds the upper bound of the array.
    ; 4 = $AV_ARRAY has more than one dimension.
    ; 5 = $AV_ARRAY is not an array.
    ;
    ; Author(s).........: teh_hahn <[email='sPiTsHiT@gmx.de'][/email]>
    ; Company...........: None
    ; URL...............: None
    ; Note(s)...........: None
    ;===============================================================================
    Func _ArrayAverage(ByRef Const $av_array, Const $I_START = 0, $i_end = 0)
    Local Const $I_SIZE = (UBound($av_array) - 1)
    If @error Then Return (SetError(5, 0, 0))

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

    If UBound($av_array, 0) > 1 Then Return (SetError(4, 0, 0))

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

    If $i_end > $I_SIZE Then Return (SetError(3, 0, 0))
    If Not $i_end Then $i_end = $I_SIZE

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

    If $I_START > $I_SIZE Then Return (SetError(2, 0, 0))
    If $I_START > $i_end Then Return (SetError(1, 0, 0))

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

    Local $n_ave = 0
    For $i = $I_START To $i_end
    $n_ave += $av_array[$i]
    Next

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

    Return ($n_ave / $i)
    EndFunc ;==>_ArrayAverage

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

    main()

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

    Func main()
    Local Const $i_end = 15000
    Local Const $I_MODE = 1

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

    Local $n_timer = 0, $an_time0[($i_end + 1)], $an_time1[($i_end + 1)], $an_time2[($i_end + 1)]
    For $j = 1 To $i_end
    $n_timer = TimerInit()
    If $I_MODE <> 1 And $I_MODE <> 2 And $I_MODE <> 9 And $I_MODE <> 10 And $I_MODE <> 17 And $I_MODE <> 18 And $I_MODE <> 25 And $I_MODE <> 26 And _
    $I_MODE <> 33 And $I_MODE <> 34 And $I_MODE <> 41 And $I_MODE <> 42 And $I_MODE <> 65 And $I_MODE <> 66 And $I_MODE <> 72 And _
    $I_MODE <> 74 And $I_MODE <> 129 And $I_MODE <> 130 And $I_MODE <> 137 And $I_MODE <> 138 Then Return SetError(6, 0, 0)
    $an_time0[$j] = TimerDiff($n_timer) * 1000

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

    $n_timer = TimerInit()
    Local $ai_ok[20] = [1, 2, 9, 10, 17, 18, 25, 26, 33, 34, 41, 42, 65, 66, 72, 74, 129, 130, 137, 138]
    Local $i_err = 1
    For $i = 0 To 19
    If $ai_ok[$i] = $I_MODE Then
    $i_err = 0
    ExitLoop
    EndIf
    Next
    If $i_err Then Return SetError(6, 0, 0)
    $an_time1[$j] = TimerDiff($n_timer) * 1000
    $i_err = 1

    $n_timer = TimerInit()
    If Not StringInStr("|1|2|9|10|17|18|25|26|33|34|41|42|65|66|72|74|129|130|137|138|", "|" & $I_MODE & "|") Then Return SetError(6, 0, 0)
    $an_time2[$j] = TimerDiff($n_timer) * 1000
    Next

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

    Exit MsgBox(64, "Debug", "Or-Mode: " & _ArrayAverage($an_time0) & @CR & "Array-Mode: " & _ArrayAverage($an_time1) & @CR & "String-Mode: " & _ArrayAverage($an_time2))
    EndFunc ;==>main

    [/autoit]

    Beim Versuch mit 1 (erster Treffer)
    1. Or-Methode (ca. 11ms)
    2. String-Methode (ca. 13ms)
    3. Array-Methode (ca. 36ms)

    Beim Versuch mit 138 (letzter Treffer)
    1. String-Methode (ca. 19ms)
    2. Or-Methode (ca. 29ms)
    3. Array-Methode (ca. 100ms)

    Bin von der String-Methode stark begeistert! Wenig Code, aber im Schnitt am schnellsten. Mal wieder was dazu gelernt!
    Mir fällt grade auf, wie krank das ist, für sowas überhaupt Zeit zu investieren, aber nun gut!

    Vielen Dank für alle Vorschläge!