Ini2Array() : Ini-Datei in Array einlesen + IniGetAllKeys() : Array mit allen vorkommenden Keys einer Ini-Datei erzeugen

  • Meine "gefixte" Version wäre so HansJ54 :

  • Zeile 12: gute Idee

    Zeile 15: wenn etwas nicht passt (Filename oder Inhalt), dann sollte abgebrochen werden. Normalerweise sind die Daten ja nicht eingebettet, ich schreibe die z.B. regelmäßig von den Clients aus in eine gemeinsame Ini-Datei.

    Zeile 19: sehr gut, hatte auch mal testweise eine Sektion "1234" probiert, führte zum Error. Habe aber nicht sofort verstanden warum - jetzt ist es mir klar. Daher konnte ich die Anzahl in Zeile 54 auch nicht setzen und musste oben UBound nutzen.


    Bei Sortieren ergibt sich noch ein Problem mit den Versionen. Hat jetzt nicht mit der Funktion allgemein zu tun, sondern nur mit meiner Anwendung. Aber vielleicht gibt es da ja auch schon eine Lösung für die Sortierung von Versionsnummern? 99.0.1234.741 würde jetzt fälschlich als "neuer" eingeordnet als 105.0.1234.102.


    Andy: Projekt erfolgreich abgeschlossen, die Überschrift des Threads passt?

  • HansJ54 : Zu Zeile 15 ja aber dein @error grift ja nicht, da es sich auf diene Funktion IniReadSectionNames bezieht und du diesen dort garnicht setzt. Du musst solch einen Fehler ansonsten innerhalb der Funktion definieren und dort dann auch @error (ggf. auch @extended) setzen. Bitte korrigiert mich aber @error dürfte in diesem Fall auch bei Fehlern innerhalb der Funktion niemals triggern.

    Wegen dem sortieren: Autoit betrachtet die Versionsnummer als String und eine 9 ist größer als die 1. Ich weiß aktuell keinen guten Workaround dafür. Ich habe das bei mir mal damit gelöst mit einer zus. Spalte wo über Stringsplit auf den Punkt der Vordere Teil als Zahl interpretiert wird und somit richtig sortiert und danach diese Hilfsspalte gelöscht wird. Aber das war in dem Fall nur ein 1D-Array, das wird bei so einem wie hier ggf. schwer.

  • Moombas : Zeile 15 - IniReadSectionNames ist eine vorhandene Funktion und liefert schon einen @error. Der Fehler lag in meiner IniGetAllKeys, da muss auch noch eine Errorbearbeitung hin. Falls die Ini-Datei $sIni nicht vorhanden ist, dann braucht es m.E. insgesamt 4 "If @error then". Bitte mal meine Logik prüfen.


    Versionsnummern sortieren: da denke ich gerade drüber nach, kommt ;)


  • Ich weiß aktuell keinen guten Workaround dafür.

    AutoIt
    $ver1 = "99.0.1234.741"
    $ver2 = "105.0.1234.102"
    
    ConsoleWrite('String, ver1 > ver2: ' & ($ver1 > $ver2) & @CRLF) ; Stringvergleich
    ConsoleWrite('Number, ver1 > ver2: ' & (Number($ver1) > Number($ver2)) & @CRLF) ; Erzwinge nummerischen Vergleich
    ConsoleWrite('Number, ver2 > ver1: ' & (Number($ver2) > Number($ver1)) & @CRLF) ; Erzwinge nummerischen Vergleich

    Greift aber nur dann, wenn die ersten beiden Blöcke, die als Kommazahl interpretiert werden, sich unterscheiden.

    Für eine genaue Unterscheidung die Blöcke splitten und nacheinander abgleichen.


    EDIT:

    Hier mal eine Vergleichsfunktion, die Versionsnummern können auch unterschiedlich lang sein.

  • HansJ54 : Hast du Recht, ich war da irgendwie bei einer eigenen Funktion. Sorry dafür ;)

    BugFix : Das würde bedeuten, das du jede einzelne Zeile selber durcharbeiten müsstest und auch die Sortierung in diesem 2D-Array komplett selber erledigen musst. Ich war von der Verwendung des vorhandenen _ArraySort() ausgegangen mit meiner Aussage, dem genau das Begreiflich zu machen.


    Aber ich habe das hier gefunden: https://www.autoitscript.com/f…ndComment&comment=1347110

  • Ich sollte mal schneller hier reinschauen, bei mir sind es bisher mehr als 30 Zeilen Code und AspirinJunkie macht das mit 5 8)

    Es funktioniert einwandfrei für meine Fälle, allerdings vom Verstehen bin ich ganz weit entfernt. :Face:


    AspirinJunkie Im Beispiel unten gibt es ein Problem mit der Sortierung der "Release #nn" - da klappt die Sortierung (#29 vor #2) nicht - für mich nicht wichtig, kommt bei mir nicht vor.

    Und: Deine ArrayPlus-UDF ist super, Einiges kann ich auch benutzen weil ich es verstehe, aber z.B. für das Beispiel unten nur das Maximum oder die Zeile des Maximums zu ermitteln dazu reicht es bei mir nicht. Ebenfalls kein großes Problem, da ich mit der Sortierung das Ergebnis auch bekomme, aber vielleicht gibt es ja auch die entsprechende direkte Funktion bei Dir? Und ist "Array-Plus-UDF" der Nachfolger von "DynArray"?


    Nochmals vielen Dank an alle hier im Forum!



  • Ich sollte mal schneller hier reinschauen, bei mir sind es bisher mehr als 30 Zeilen Code und AspirinJunkie macht das mit 5 8)

    Es funktioniert einwandfrei für meine Fälle, allerdings vom Verstehen bin ich ganz weit entfernt. :Face:

    Die meisten Sortierfunktionen (gibt Ausnahmen wie Radix oder tlw. Bucketsort) basieren auf einem Größer/Kleiner-Vergleich von jeweils 2 Elementen. Also irgendwo im Sortieralgorithmus wird geschaut ob von den beiden gerade betrachteten Elemente das erste größer oder kleiner ist als das andere und dementsprechend werden die dann neu eingereiht.
    Das normale Arraysort nimmt ganz einfach den AutoIt-internen Vergleich von 2 Variablen ($A > $B bzw. $A < $B).

    Das klappt bei Zahlen und auch den meisten Strings ganz gut - bei speziellen Sachen - wie eben bei dir - bringt der jeweilige Größenvergleich nicht das gewünschte Ergebnis.
    Daher wäre es ganz gut, wenn man für diese Fälle eine Sortierfunktion hätte, wo man selbst angeben kann wie der Größer/Kleiner-Vergleich gemacht werden soll. Exakt das macht meine Funktion _ArraySortFlexible.
    Nun zum konkreten "NaturalSort". Die Größer/Kleiner-Vergleichsfunktion hierzu welche auch bei Versionsnummern und Zahlen innerhalb des Strings ordentlich größer/kleiner für die Sortierung zurückgibt kann man natürlich in reinem AutoIt schreiben.
    Das ist etwas aufwendig aber machbar (haben wir irgendwo schonmal im Forum hier gemacht).

    Einfacher ist es jedoch sich einfach die Vergleichsfunktion zu nehmen, welche der Windows Explorer für seine Sortierung verwendet.
    Die macht nämlich genau das was wir wollen.

    Diese heißt StrCmpLogicalW und die Funktion _MyCompare aus meinem Beispiel macht nichts weiter, als diese Funktion mit den AutoIt-Variablen aufzurufen und das Ergebnis zurückzugeben - sprich: ein Wrapper für diese Funktion.

    AspirinJunkie Im Beispiel unten gibt es ein Problem mit der Sortierung der "Release #nn" - da klappt die Sortierung (#29 vor #2) nicht - für mich nicht wichtig, kommt bei mir nicht vor.

    Nach der zweiten Spalte wird überhaupt nicht sortiert - nur nach der ersten.

    Möchte man, wenn die 1. Spalte gleich groß ist, anschließend nach der 2. Spalte sortieren, dann muss man die Vergleichsfunktion noch entsprechend anpassen:


    aber z.B. für das Beispiel unten nur das Maximum oder die Zeile des Maximums zu ermitteln dazu reicht es bei mir nicht.

    Wenn es ebenfalls mit dem Natural-Sort das Min/Max bestimmt werden soll dann so:


    Ohne spezielle Anforderungen an die Datentypen ist es entsprechend einfacher:



    Und ist "Array-Plus-UDF" der Nachfolger von "DynArray"?

    Teils. Die Hauptaufgabe der Dynarray ist es dynamische Arrays in AutoIt zu haben.
    Mit der Einführung von Maps und insbesondere dessen Funktion MapAppend ist diese Aufgabe ein Stück obsolet geworden.
    Daneben diente die UDF aber auch als Container für weitere Array-Funktionen von mir, welche da streng genommen eigentlich thematisch nicht reingehören. Diese liegen nun redundant auch in der ArrayPlus.au3.
    Ich müsste daher die DynArray mal aufräumen und auf deren eigentlichen Zweck hin wieder entschlacken.

    Die nicht-dynamischen Arrayfunktionen sind jetzt in der ArrayPlus-UDF zu finden.



    So und nun zurück in den Urlaubsmodus und mit den Kindern an die Strandbar... 8)

  • AspirinJunkie : Aber nicht im Urlaub stören lassen, hat Zeit und mit Workaround gelöst!

    _ArrayMinMax() hat keinen Range, den man für die Untersuchung angeben kann (z.B. Zeile 2-9 + Spalte 2-4)?


    Kann man einem neuen Array direkt einen Range aus einem bestehenden Array zuweisen? Also $aB = (Zeile 2-9 und Spalte 2-4) aus Array $aA? Habe mal wieder nichts gefunden. Mein Workaround: ich kopiere das Array komplett und lösche die nicht gewünschten Zeilen und Spalten anschließend.


  • _ArrayMinMax() hat keinen Range, den man für die Untersuchung angeben kann (z.B. Zeile 2-9 + Spalte 2-4)?

    Dafür gibt es ja _ArraySlice (siehe unten).
    Wenn man die Spalten eingrenzt wird man aber dann Schwierigkeiten haben das Ergebnis zu interpretieren, da die Spalten an jeweils anderen Stellen stehen.


    Kann man einem neuen Array direkt einen Range aus einem bestehenden Array zuweisen? Also $aB = (Zeile 2-9 und Spalte 2-4) aus Array $aA?

    AutoIt
    _ArraySlice($aArray, "[1:8][1:3]")
  • Du hast recht mit der Interpretation (außer man schneidet nur am Ende Spalten ab) und _ArraySlice() ist die perfekte Lösung.

    Für mich sind es allerdings sowieso auch nur Zeilen, die erste und ab einer bestimmten Zeile unten soll nicht ausgewertet werden.


    Und so sieht mein Ergebnis aus (Update):


  • AspirinJunkie

    Vielen Dank für Arrayplus.au3, nutze ich jetzt ausgiebig.

    Frage dazu: ich ziehe mit _ArraySlice($aArray, "[2:6][::1]") einen Zeilenbereich raus, wobei [::1] für "alle Spalten" steht. Ist das der richtige Parameter dafür oder gibt es ein "all"?