• Hi,

    da es mich immer wieder nervte, wenn ich mehrere Zahlen miteinander vergleichen musste, und mit der Funktion _Max() nur zwei gleichzeitig vergleichen konnte, habe ich diese kleine UDF geschrieben, um x-beliebig viele Zahlen miteinander zu vergleichen lassen (hab sie noch nicht allzu oft getestet).

    Um die einzelnen Zahlen voneinander zu trennen fungieren alle Zeichen, außer Zahlen und dem "-"-Zeichen, sowie dem "."-Zeichen, da die Funktion sonst keine negativen Zahlen und keine Kommazahlen erkennt, es funtkionieren auch Leerzeichen, ebenso Buchstaben. ;)

    Mittels dem $Flag-"Parameter" kann entschieden werden, ob die Funktion die größte Zahl oder die kleinste Zahl zurückgeben soll.
    $Flag = 0, bedeutet die Größte.
    $Flag <> 0, bedeutet die Kleinste.

    !!!ACHTUNG: Nicht mehr aktuell bitte im Spoiler für richtige Informationen nachschauen.

    Spoiler anzeigen
    [autoit]


    ;#_SortMinMax-FUNKTION-Start#======================================================================================
    ;Funktion:.................._SortMinMax
    ;Autor:.....................Ealendil (http://www.AutoIt.de)
    ;Beschreibung:..............gibt bei Erfolg ein Array zurück, welches von der höchsten
    ; zur kleinsten bzw. umgekehrt sortiert ist.
    ;Infos:.....................$Nr_1_to_Nr_n = Hier die Zahlen zum Vergleichen eingeben,
    ; diese müssen als String ("1,2,3,...") oder ('1,2,3,...')
    ; eingegeben werden.
    ; Es funktioniert ebenso mit einem Array,
    ; dieses muss allerdings 0-basiert sein.
    ;
    ; $SortMax = 1 bedeutet das die Funktion ein Array zurückgibt, welches
    ; folgendermaßen ausschaut:
    ; $Array[0] = Anzahl der zurückgegebenen Zahlen
    ; $Array[1] = höchste Zahl
    ; $Array[2] = zweithöchste Zahl
    ; $Array[3] = dritthöchste Zahl
    ;
    ; usw.
    ; $Array[n] = kleinste Zahl
    ; sollte $Sort_Max <> 1
    ; sein, so wird das Array umgekehrt sortiert zurückgegeben.
    ; $Split: hierbei kann angegeben werden, welche Zeichen zum trennen
    ; der Zahlen fungieren sollen, wird keines angegeben, so wird ","
    ; verwendet, man muss (falls ein String verwendet wird) jede Zahl mit den in
    ; $Split angegebenen Zeichen trennen.
    ;Return-Werte:..............ein Array, welches von der höchsten zur kleinsten bzw. umgekehrt
    ; sortiert ist.
    ; $Array[0] gibt die Anzahl der zurückgegeben Zahlen an.
    ; Als Trennzeichen fungieren alle Zeichen, welche bei $Split
    ; angegeben werden, sollten keine Angegeben, so wird "," verwendet.
    ;@Error-Werte:.............
    ; @Error = 0, kein Fehler
    ; 1, $Nr_1_to_Nr_n ist kein String ,falls ein String verwendet wird.
    ; 2, $Sort_Max ist entweder keine Zahl oder 0.
    ;#_SortMinMax-FUNKTION-End#========================================================================================
    Func _SortMinMax($Nr_1_to_Nr_n, $Sort_Max = 1, $Split = '')

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

    ;Prüft ob $Sort_Max ein Integer ist, falls nicht, wird die Funktion verlassen.
    If Not IsInt($Sort_Max) Then Return SetError(2, 0, 0)

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

    Local $i, $Str = '', $i_i, $i_i_i, $i_Copy = 0

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

    ;Prüft ob Zeichen für $Split vorhanden sind, falls nicht, dann $Split = ','.
    If $Split = '' Then $Split = ','

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

    ;Prüft ob $Nr_1_to_Nr_n ein Array ist. Falls dies zutrifft, wird ein String erstellt,
    ;welches jedes Zeichen, in $Split eingegebenen Zeichen, voneinander trennt.
    If IsArray($Nr_1_to_Nr_n) Then
    Local $Str_Trim = ''
    For $i = 0 To UBound($Nr_1_to_Nr_n) - 1
    $Str_Trim &= $Nr_1_to_Nr_n[$i] & $Split
    Next
    $Str = StringTrimRight($Str_Trim, 1)
    Else
    $Str = $Nr_1_to_Nr_n

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

    ;Prüft ob $Str ein String ist, falls nicht wird die Funktion verlassen.
    If Not IsString($Str) Then Return SetError(1, 0, 0)
    EndIf

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

    ;"Haupt"-String wird nun gesplitet.
    Local $sp = StringSplit($Str, $Split, 0), $aMax[$sp[0] + 1], $Zahl_Min = -9223372036954775808

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

    ;Weißt $aMax[0] die Anzahl der Elemente zu und weißt jedem Element in $Sp die Nummer zu,
    ;die das jeweilige Element darstellt.
    $aMax[0] = $sp[0]
    For $i = 0 To $sp[0]
    $sp[$i] = Number($sp[$i])
    Next

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

    ;Weißt jedem Element in $aMax $Zahl_Min zu
    For $i = 1 To $sp[0]
    $aMax[$i] = $Zahl_Min
    Next

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

    ;Sortiert nun alle Zahlen von der Höchsten zur Kleinsten und weißt ihnen die entsprechenden Elemente
    ;in $aMax zu.
    For $i_i = 1 To $sp[0]
    For $i = 1 To $sp[0]
    If $sp[$i] > $aMax[$i_i] Then
    $aMax[$i_i] = $sp[$i]
    $i_i_i = $i
    EndIf
    Next
    $sp[$i_i_i] = $Zahl_Min
    Next

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

    ;Sollte der $Sort_Max Parameter <> 1 sein, also, soll das Array von der kleinsten zur höchsten Zahl
    ;sortiert sein, dann wird nun ein weiteres Array erstellt, welches jedes Element von $aMax enthält und
    ;alle Zahlen entsprechend miteinander vertauscht.
    ;Anschließend wird das neu sortierte Array zurückgegeben.
    If Not $Sort_Max = 1 Then
    Local $aMax_Copy[$sp[0] + 1]
    For $i = 1 To $aMax[0]
    $aMax_Copy[$i] = $aMax[$i]
    Next
    For $i = $aMax[0] To 1 Step -1
    $i_Copy += 1
    $aMax[$i] = $aMax_Copy[$i_Copy]
    Next
    Return $aMax
    Else
    Return $aMax
    EndIf
    EndFunc ;==>_SortMinMax

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

    #include <Array.au3>

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

    $test = _SortMinMax('2,34,356256,7843,9787945.67,-4,-245246,346', 1, ',')
    _ArrayDisplay($test)
    $try = _SortMinMax('-2,-34453.67434,57342', 0, ',')
    _ArrayDisplay($try)
    Dim $array[7]
    $array[0] = '1'
    $array[1] = 2
    $array[2]= 235425.5421
    $array[3]= -35326.352462
    $array[4]='3523'
    $array[5]=556578457546.454
    $array[6]='3456534.34653'
    $tryit = _SortMinMax($array)
    _ArrayDisplay($tryit)

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


    Da ich die Funktion noch nicht ausführlich getestet habe, bitte um Feedback.

    Hoffe sie hilft jemandem.

    LG

    Ealendil


    #Edit1: Rechtschreibung korrigiert.
    #Edit2: Es funktioniertem nur noch "," und Leerzeichen als Trennzeichen.
    #Edit3: Man kann nun die Trennzeichen frei wählen, sowie wurde die Arbeitsweise verändert, Kommazahlen, werden nun auch unterstützt. Erklärungen dazu geschrieben. Name der Func() geändert. Statt dem String kann auch ein 0-basiertes Array verwendet werden.

  • Hi,
    ist nicht böse gemeint, soll nur dazu anregen "genauer hinzuschauen", deswegen auch so eine penible Auflistung im Folgenden. Die UDF hat leider mehrere Fehler/Probleme:

    • Im ersten Schleifendurchlauf werden alle Werte nach Integer gecastet, dadurch Kommazahlen nicht vergleichbar.
    • $Max wird mit 0 initialisiert, dadurch Vergleich von ausschließlich negativen/natürlichen Zahlen (je nach zweitem Parameter) nicht möglich.
    • Aufruf von UBound() bei jeder Iteration, StringSplit() ohne zweiten Parameter liefert in Array-Element [0] eben diesen Wert ohne Ressourcenverschwendung.
    • Split des ersten Parameters zu ungenau, UDFs sollten klare Vorgaben liefern.
    • Prüfung am Ende sinnlos, da zuvor alles nach Integer gecastet wurde.
    • Initialisierung von Schleifenvariablen überflüssig.
    • Name der UDF / Einsatz des zweiten Parameters meiner Meinung nach "unglücklich".


    Hier der erweiterte/korrigierte Quellcode, der in zwei Funktionen unterteilt wurde, sauber nach "AutoIt v3" Coding-Standards (hoffe mir sind nicht noch Fehler unterlaufen, ansonsten kurzer Hinweis bitte):

    Spoiler anzeigen
    [autoit]

    #include-once

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

    ; #INDEX# =======================================================================================================================
    ; Title .........: fwMath
    ; AutoIt Version : 3.3++
    ; Language ......: English
    ; Description ...: This library contains mathematical functions.
    ; Author(s)......: teh_hahn
    ; ===============================================================================================================================

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

    ; #CURRENT# =====================================================================================================================
    ; _Maximum
    ; _Minimum
    ; ===============================================================================================================================

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

    ; #INTERNAL_USE_ONLY#============================================================================================================
    ; __MaxMinIsValid
    ; __MaxMinToNumber
    ;================================================================================================================================

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

    ; #FUNCTION# ====================================================================================================================
    ; Name...........: _Maximum
    ; Description ...: Evaluates which of the numbers is higher.
    ; Syntax.........: _Maximum($vNumbers)
    ; Parameters ....: $vNumbers - String containing the numbers, separated by "|".
    ; Return values .: Success - The higher of the numbers.
    ; Failure - False, sets @error to 1 if $vNumbers is invalid.
    ; Author ........: Ealendil
    ; Modified.......: teh_hahn
    ; Remarks .......:
    ; Related .......:
    ; Link ..........:
    ; Example .......: No
    ; ===============================================================================================================================
    Func _Maximum($vNumbers)
    Local $nMax = 0

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

    ;~ Check if the number string is invalid.
    If Not __MaxMinIsValid($vNumbers) Then Return SetError(1, 0, False)

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

    ;~ Split up the number string into substrings.
    $vNumbers = StringSplit($vNumbers, "|")

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

    ;~ Convert all elements in the passed array to numbers.
    __MaxMinToNumber($vNumbers)

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

    ;~ Set the highest number to the first number in the array.
    $nMax = $vNumbers[1]

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

    ;~ Determine the highest number.
    For $i = 1 To $vNumbers[0]
    If $vNumbers[$i] > $nMax Then $nMax = $vNumbers[$i]
    Next

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

    Return $nMax
    EndFunc ;==>_Maximum

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

    ; #FUNCTION# ====================================================================================================================
    ; Name...........: _Minimum
    ; Description ...: Evaluates which of the numbers is lower.
    ; Syntax.........: _Minimum($vNumbers)
    ; Parameters ....: $vNumbers - String containing the numbers, separated by "|".
    ; Return values .: Success - The lower of the numbers.
    ; Failure - False, sets @error to 1 if $vNumbers is invalid.
    ; Author ........: Ealendil
    ; Modified.......: teh_hahn
    ; Remarks .......:
    ; Related .......:
    ; Link ..........:
    ; Example .......: No
    ; ===============================================================================================================================
    Func _Minimum($vNumbers)
    Local $nMin = 0

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

    ;~ Check if the number string is invalid.
    If Not __MaxMinIsValid($vNumbers) Then Return SetError(1, 0, False)

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

    ;~ Split up the number string into substrings.
    $vNumbers = StringSplit($vNumbers, "|")

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

    ;~ Convert all elements in the passed array to numbers.
    __MaxMinToNumber($vNumbers)

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

    ;~ Set the lowest number to the first number in the array.
    $nMin = $vNumbers[1]

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

    ;~ Determine the lowest number.
    For $i = 1 To $vNumbers[0]
    If $vNumbers[$i] < $nMin Then $nMin = $vNumbers[$i]
    Next

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

    Return $nMin
    EndFunc ;==>_Minimum

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

    ; #INTERNAL_USE_ONLY#============================================================================================================
    ; Name...........: __MaxMinIsValid
    ; Description ...: Helper function to determine if the number string of _Maximum / _Minimum is valid.
    ; Syntax.........: __MaxMinIsValid(Const $S)
    ; Parameters ....: $S - String containing the numbers, separated by "|".
    ; Return values .: Success - True
    ; Failure - False
    ; Author ........: teh_hahn
    ; Modified.......:
    ; Remarks .......: For internal use only.
    ; Related .......:
    ; Link ..........:
    ; Example .......: No
    ; ===============================================================================================================================
    Func __MaxMinIsValid(Const $S)
    Return StringRegExp($S, "^(?:(-?\d*.?\d+)+?\|)+?(?1)$")
    EndFunc ;==>__MaxMinIsValid

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

    ; #INTERNAL_USE_ONLY#============================================================================================================
    ; Name...........: __MaxMinToNumber
    ; Description ...: Helper function to convert a string-array to a numeric-array.
    ; Syntax.........: __MaxMinToNumber(ByRef $avNumbers)
    ; Parameters ....: $avNumbers - Integer specifying the direction to traverse through the array-dimension:
    ; Return values .: None
    ; Author ........: teh_hahn
    ; Modified.......:
    ; Remarks .......: For internal use only.
    ; Related .......:
    ; Link ..........:
    ; Example .......: No
    ; ===============================================================================================================================
    Func __MaxMinToNumber(ByRef $avNumbers)
    For $i = 1 To $avNumbers[0]
    $avNumbers[$i] = Number($avNumbers[$i])
    Next
    EndFunc ;==>__MaxMinToNumber

    [/autoit]


    Dies soll wie gesagt nur "Lerneffekt" haben, Die UDFs _ArrayMin und _ArrayMax ist besser für diesen Anwendungszweck geeignet!

  • Hi,

    teh_hahn: Nehm ich nicht böse auf, hab ja um Feedback gebeten...hab nun die Funktionsweise beinahe komplett verändert, siehe Post#1. Vielen Dank für die Krtitk übrigens.
    Der Grund für die Func() war: wieder was zu lernen, immer mehr in AutoIt zu denken und weil ich sie gebraucht hab.

    @MathiasG.: Dachte mir doch, ich hab irgendwo schonmal im Forum so eine ähnliche Func() gesehen....der Grund, warum ich meine Func() allerdings geschrieben habe, war, dass ich auch mit Strings vergleichen wollte.... hab mir auch ein bisschen was von deiner Func() abgeschaut ;)


    LG Ealendil

    3 Mal editiert, zuletzt von Ealendil (17. Februar 2010 um 22:13)

  • Hallo nochmal!

    Du könntest theoretisch direkt an meine Funktion den Return-Wert von _String_Split übergeben :P
    Freut mich, dass meine UDF Anwendung findet. :)

  • Hi,

    mittlerweile macht Deine Funktion ja etwas völlig anderes als noch zuvor. Wenn ich das richtig verstehe, möchtest Du nun Ganzzahlen sortieren können (sowohl auf- als auch absteigend) und Du möchtest sowohl Strings als auch Arrays übergeben können. Es besteht aber immer noch das Gleiche Problem wie zuvor: Der Funktion fehlt die Eindeutigkeit um als UDF durchzugehen. Des Weiteren wird Performance unnötigerweise verschwendet, da Arrays hin und her kopiert werden und bei einer Sortierung von der niedrigsten zur höchsten Ganzzahl zunächst andersherum sortiert wird! Deklarationen wie $Zahl_Min = -9223372036954775808 sind immer zu vermeiden, da sich der Wertebereich eines Integers von 32Bit auf 64Bit (oder sogar 128Bit) ändert (weiß spontan aber nicht, wie das bei AutoIt v3 ist),

    Wozu der ganze Quellcode? Das Ganze lässt sich z.B. auf Folgendes zusammenfassen. Hier allerdings ohne $array[0] mit Anzahl der Elemente, ließe sich aber sehr simpel ändern. Auch wurde der Separator erneut festgesetzt und falls ein String übergeben wird, wird dieser validiert.

    Spoiler anzeigen
    [autoit]

    #include-once

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

    #include <Array.au3>

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

    Func _MaxMinSort($vNumbers, Const $fMIN = False)
    Local $iEnd = 0
    If Not IsArray($vNumbers) Then
    If Not StringRegExp($vNumbers, "^(?:(-?\d*.?\d+)+?\|)+?(?1)$") Then Return SetError(1, 0, False)
    $vNumbers = StringSplit($vNumbers, "|", 2)
    EndIf

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

    $iEnd = UBound($vNumbers) - 1
    For $i = 0 To $iEnd
    $vNumbers[$i] = Number($vNumbers[$i])
    Next

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

    _ArraySort($vNumbers, $fMIN)

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

    Return $vNumbers
    EndFunc ;==>_MaxMinSort

    [/autoit]


    Deine Beispiele dazu:

    Spoiler anzeigen
    [autoit]

    Global $anArray[7] = ['1', 2, 235425.5421, -35326.352462, '3523', 556578457546.454, '3456534.34653']
    Global $avTest[3] = ["2|34|356256|7843|9787945|67|-4|-245246|346|1", "-2|-34453.67434|57342", $anArray]
    Global $avResult = 0

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

    For $vTest In $avTest
    $avResult = _MaxMinSort($vTest)
    _ArrayDisplay($avResult)
    Next

    [/autoit]


    Ich merke dies nur kritisch an, da Deine Funktion in Deiner Signatur als UDF auftaucht und es bei Neulingen bzw. Einsteigern den Eindruck erwecken könnte, dass diese für den Produktiveinsatz geeignet ist. Dies ist meiner Meinung nach nicht der Fall. Die Verwendung von "Standard" UDFs wie _ArraySort, _ArrayMin und _ArrayMax ist absolut vorzuziehen, da diese erprobt sind und sich auf eine Aufgabe fokussieren.

    Wie zuvor auch: Ist nur als konstruktive Kritik und als Hilfe für hier Lesende gedacht!

  • Hi,

    teh_hahn:

    Danke für deine Mühe mir das zu erklären.

    Nun ich habe die Func() deswegen reingestellt, und verändert um zu lernen, Fehler zu begehen, diese auzubessern um daraus zu lernen (hab ich irgendwo schonmal gelesen), um mich dadurch zu verbessern.

    Es stimmt das schon das ich die Func() auf ein Minimum konzentrieren könnte, doch dann müsste ich eine schon bereits geschriebene UDF verwenden, dass tue ich auch immer wieder, doch wenn ich lernen möchte, wie es hierbei der Fall ist,
    dann verwende ich nur Standardfunktionen.

    Gut fand ich deinen vorletzten Satz, dadurch wird einiges schlüssiger...Ich hab meine Signatur nun verändert.

    Die Func() habe ich deswegen UDF genannt, da unter UDF eigtl. alles fällt was von einem Benutzer mittels Func ....() #Befehle# EndFunc geschrieben wird, dass es vlt. nicht produktiv ist, hab ich nie behauptet, hast du glaub ich, aber auch nicht gesagt.
    Soviel mal dazu.

    Das ich $array[0] = Anzahl der Elemente, hab ich deswegen gemacht, falls mal jmd. in Verlegenheit kommt und die Func() nutzt, dass er/sie nicht UBound() die Größe abfragen muss.

    Bzgl. Quellcode: lösch mal alle Kommentare und unnötigen Zeilenabstände weg, im Endeffekt bleiben 46 Zeilen Code (nur die Func alleine übrig). Vergleich _ArraySort+ mit verwendeter Funcs() (bei _ArraySort) knapp 132 Zeilen.

    Inwiefern fehlt der Funktion noch die Eindeutigkeit?

    Ich wollte damit nur zeigen, wie man "Zahlen"-Arrays sortieren, die größte/kleinste Zahl in einem Array herausfindet, deswegen dann auch die ganzen Kommentare dazu.
    Im Endeffekt ein Beispiel, obwohl es auch besser geht...bin noch Anfänger.

    LG

    Ealendil

    4 Mal editiert, zuletzt von Ealendil (18. Februar 2010 um 23:17)

  • Hi,

    Zitat

    Nun ich habe die Func() deswegen reingestellt, und verändert um zu lernen, Fehler zu begehen, diese auzubessern um daraus zu lernen (hab ich irgendwo schonmal gelesen), um mich dadurch zu verbessern.


    Absolut. Dafür ist dieses Forum ja auch da!

    Zitat

    Bzgl. Quellcode: lösch mal alle Kommentare und unnötigen Zeilenabstände weg, im Endeffekt bleiben 46 Zeilen Code (nur die Func alleine übrig). Vergleich _ArraySort+ mit verwendeter Funcs() (bei _ArraySort) knapp 132 Zeilen.


    Absolut. Unter diesem Gesichtspunkt ist es weniger Quellcode. Bestehende Funktionen zu nutzen hat allerdings immer einen Vorteil: Muss etwas geändert werden, so kann dies an einer Stelle erledigt werden (Vermeidung von Redundanzen). Des Weiteren ist es immer gut, bestehende Schnittstellen zu nutzen.

    Zitat

    Inwiefern fehlt der Funktion noch die Eindeutigkeit?


    Ist schon etwas besser, anscheinend war die Version im Spoiler unterschiedlich zu der im Anhang. Problematisch ist immer noch:

    • Der $Split Parameter. Übergebe der Funktion z.B. mal "." oder 2 und z.B. Eine Zeichenkette mit mehr als einem Zeichen.
    • Der $Nr_1_to_Nr_n Parameter. Übergebe z.B. ein 2D-Array und eine deklarierte Variable (nicht initialisiert, sprich einfach nur Local $vTest).
    Zitat

    Die Func() habe ich deswegen UDF genannt, da unter UDF eigtl. alles fällt was von einem Benutzer mittels Func ....() #Befehle# EndFunc geschrieben wird, dass es vlt. nicht produktiv ist, hab ich nie behauptet, hast du glaub ich, aber auch nicht gesagt.


    Ja, leider ist AutoIt da (auch in der Hilfedatei) viel zu ungenau. Eine UDF (User Defined Function) ist eine Benutzerfunktion, die mittels bestimmter Coding-Standards strukturiert entwickelt, kommentiert und ausführlich wurde. Sie ist so programmiert das sie über ein bestimmtes Projekt hinaus verwendet werden kann und erfüllt somit das Merkmal der Wiederverwendbarkeit. Dies steht in dieser Form nirgendwo niedergeschrieben, würde ich aber mal als grobe Definition nehmen.
    Meiner Meinung nach fallen darunter z.B. folgende Eigenschaften, damit die Funktion zur UDF wird:

    • Einhaltung von http://www.autoitscript.com/autoit3/scite/…F_Standards.htm
    • Verwendung von [autoit]#AutoIt3Wrapper_Au3Check_Parameters=-q -d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6
      Opt("MustDeclareVars", 1)[/autoit] während der Entwicklung der UDF/UDF-Bibliothek.
    • Der Name interner Funktionen in der UDF-Bibliothek beginnt mit "__".
    • UDFs sollten keine Global-Variablen verwenden, es sei denn es handelt sich um eindeutig definierte Konstanten.
    • Versuch der Typisierung der Funktionsparameter, sprich: Kein 0/1 für Boolesche Werte (macht die Standard UDF-Bibliothek leider) sondern False/True. Abfangen invalider Übergabeparameter (siehe z.B. meine StringRegExp oben). Einsatz von ByRef und Const wo möglich, aber sinnvoll.
    • Testen, Testen, Testen. 1. Schritt die eigenen UDFs dazu bringen mit einem AutoIt Fehler zu "crashen", sprich einen unbehandelten Fehler hervorzurufen, wie auch immer dies von "außen" möglich ist. 2. Fehler beheben. 3. Sinnvolle Testfälle für die UDF überlegen und Ergebnisse überprüfen. 4. Fehler beheben. usw.
    • UDF/UDF-Bibliothek hier oder im englischen Forum http://www.autoitscript.com/forum/ posten (natürlich nur, falls für private Zwecke entwickelt) und um Feedback bitten.
    • Anhand des Feedbacks die UDF/UDF-Bibliothek verbessern und erneut Testen.
    Zitat

    Ich wollte damit nur zeigen, wie man "Zahlen"-Arrays sortieren, die größte/kleinste Zahl in einem Array herausfindet, deswegen dann auch die ganzen Kommentare dazu.
    Im Endeffekt ein Beispiel, obwohl es auch besser geht...bin noch Anfänger.


    Was auch gut ist! Deine Funktion ist ja auch nicht "schlecht", da wir hier aber im UDF-Unterforum sind (Titel des Unterforums: "UDFs, Hinweise, speziellere Tutorials - hier ist Raum für Profis") ging es mir darum auf die von mir angesprochenen Dinge hinzuweisen, eben weil Neulinge/Einsteiger evtl. etwas unsensibel bzw. nicht erfahren genug sind.

    Ich denke auch, dass durch unseren Dialog in diesem Thread und besonders durch diesen Post für Lesende evtl. ein paar Dinge klarer werden. Von daher weiter so! Abschließend nochmal Deine UDF mit ein paar Verbesserungen (noch weiter zu bearbeitende Teile habe ich kommentiert):

    Spoiler anzeigen
    [autoit]

    #include-once

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

    Func _SortMinMax($vNumbers, $fMIN = False, Const $sSEPARATOR = ",")
    Local Const $iMININT = -9223372036954775808
    Local $sTmp = ""
    Local $iCount = 0
    Local $iCopy = 0

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

    ;~ ToDo: Evtl. noch nicht ausreichende Prüfung.
    If Not $sSEPARATOR Or $sSEPARATOR = "-" Or StringIsDigit($sSEPARATOR) Or IsNumber($sSEPARATOR) Then Return SetError(3, 0, False)

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

    If IsArray($vNumbers) Then
    If UBound($vNumbers, 0) <> 1 Then Return SetError(1, 0, False)
    $iCount = UBound($vNumbers) - 1
    For $i = 0 To $iCount
    $sTmp &= $vNumbers[$i] & $sSEPARATOR
    Next
    ;~ Wichtig: Separator mit einer Länge > 1 führten zuvor zu Fehlern.
    $vNumbers = StringTrimRight($sTmp, StringLen($sSEPARATOR))
    EndIf

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

    If Not StringRegExp($vNumbers, "^(?:(-?\d*.?\d+)+?\" & $sSEPARATOR & ")+?(?1)$") Then Return SetError(2, 0, False)
    $vNumbers = StringSplit($vNumbers, $sSEPARATOR)

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

    ;~ Es genügt, bei Element 1 zu beginnen.
    For $i = 1 To $vNumbers[0]
    $vNumbers[$i] = Number($vNumbers[$i])
    Next

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

    ;~ ToDo: Nicht nachvollzogen, geht auf jeden Fall noch eleganter.
    Local $avNumbers[$vNumbers[0] + 1] = [$vNumbers[0]]
    For $i = 1 To $vNumbers[0]
    $avNumbers[$i] = $iMININT
    Next

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

    For $i = 1 To $vNumbers[0]
    For $j = 1 To $vNumbers[0]
    If $vNumbers[$j] > $avNumbers[$i] Then
    $avNumbers[$i] = $vNumbers[$j]
    $iCount = $j
    EndIf
    Next
    $vNumbers[$iCount] = $iMININT
    Next

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

    If $fMIN Then
    Local $avNumbersCopy[$vNumbers[0] + 1]

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

    For $i = 1 To $avNumbers[0]
    $avNumbersCopy[$i] = $avNumbers[$i]
    Next

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

    For $i = $avNumbers[0] To 1 Step -1
    $iCopy += 1
    $avNumbers[$i] = $avNumbersCopy[$iCopy]
    Next
    EndIf

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

    Return $avNumbers
    EndFunc ;==>_SortMinMax

    [/autoit]
    • Offizieller Beitrag

    Sorry, wenn ich den Thread mal hijacke:


    Diesen Punkt möchte ich mal aufgreifen.
    Ich verfolge im EN-Forum seit einiger Zeit Beiträge, in denen es um Sinn (oder besser Unsinn) der Verwendung Globaler Variablen geht und auch generelle Empfehlungen, wann und wie deklariert werden soll:
    In den UDF-Richtlinien findest du folgendes:

    Zitat

    All variables must be declared at the beginning of the UDF with a “Local” scope and before they are used for the first time.


    In einem Beitrag von Valik fand ich folgenden Hinweis:

    Zitat

    ..don't front-load your functions with all the variable declarations. Declare variables right before they are used.


    Hier scheinen sich die Devs nicht ganz einig zu sein. Wobei Valiks Hinweis mir sinnvoller erscheint. Eine kopfgeführte Deklaration aller zu nutzenden Variablen ist zwar "schön" anzusehen, macht aber keinen tieferen Sinn. Die Deklaration bei erster Verwendung mit gleichzeitiger Wertzuweisung ist da effektiver.

    Ich kann mich erinnern, dass wir vor langer Zeit schon mal eine Diskussion zum Thema Standards in AutoIt hatten, da ja der User ziemlich frei ist, bei dem was er tut.
    Unter dem Aspekt, dass man Globale Variablen tunlichst vermeiden sollte (nähere Erläuterung hier), wär es vielleicht sinnvoll sich damit nochmals zu befassen (aber in einem eigenen Thread ;)).

  • HeHe, kein Problem BugFix. Ich sehe das Folgendermaßen:

    • Vorteil der lokalen Variablendeklaration zu Beginn: Übersichtlichkeit, Verständlichkeit, Wartbarkeit
    • Vorteil der lokalen Variablendeklaration bei erster Nutzung: ?


    Das Fragezeichen, weil ich glaube mal gehört zu haben, dass die meisten Programmiersprachen (bzw. der Linker der Sprache) ohnehin sämtliche lokalen Variablen einer Funktion bei einem Funktionsaufruf in den Speicher lädt, in welcher Reihenfolge bzw. an welcher Stelle sie in der Funktion auftauchen ist dabei irrelevant. Jemand mit mehr Erfahrung im Umgang mit Compilern/Linkern möge mich korrigieren, bzw. den tatsächlichen Sachverhalt schildern.

    Ich weiß aber, dass alle ANSI-C Standards bis C90 eine Deklaration der Variablen zu Beginn erzwungen haben. Erst mit dem Standard C99 konnten diese frei platziert werden.

    Zudem sind Zuweisungen in Programmiersprachen wohl die Anweisungen mit der geringsten Komplexität, weswegen ein Performancegrund für die Zuweisung bei erster Nutzung kaum gelten kann. Anweisungen wie z.B.:

    [autoit]

    Local $avArray[50000]

    [/autoit]


    sollten sowieso in keinem Quellcode vorkommen.