2-dimensionales Array sortieren

Stelle Fragen zur Programmierung mit Autohotkey

Moderator: jNizM

User avatar
Gurkentoepfer
Posts: 48
Joined: 24 Feb 2014, 14:52

2-dimensionales Array sortieren

23 Feb 2015, 07:35

Ich habe ein einfaches Array (keine "assoziatives") mit Werten aus einer csv-Tabelle befüllt.
Nun möchte ich das Array nach beliebigen Spalten sortieren und wieder zurück speichern.
Im Forum finde ich nur Sortier-Funktionen für Assoziative Arrays, die bei mir nicht funktionieren.
z.B.
http://ahkscript.org/boards/viewtopic.p ... array+sort
https://sites.google.com/site/ahkref/cu ... ort2darray

Wie bewerkstellige ich das für die einfache Form eines 2-dimensionalen Arrrays?

Habe den Kern des Problems mal herauskopiert (der Einfachheit halber befülle ich das Array nicht aus der csv-Datei,
sondern "manuell")

Code: Select all


; Problemstellung Array sortieren
;
; Tabelle:
;
; Nr | Name    | PLZ   | Straße
;----------------------------------------------
; 1  | Müller  | 90547 | Hubertusring
; 2  | Schmidt | 31852 | Steigenberger Str.
; 3  | Huber   | 91522 | Wilhelm-Busch-Str
; 4  | Meier   | 23552 | Marzipanstraße



TestArray:=[]
TestArray[0,1]:="Nr"
TestArray[0,2]:="Name"
TestArray[0,3]:="PLZ"
TestArray[0,4]:="Straße"
TestArray[1,1]:=1
TestArray[1,2]:="Müller"
TestArray[1,3]:=90547
TestArray[1,4]:="Hubertusring"
TestArray[2,1]:=2
TestArray[2,2]:="Schmidt"
TestArray[2,3]:=31852
TestArray[2,4]:="Steigenberger Str"
TestArray[3,1]:=3
TestArray[3,2]:="Huber"
TestArray[3,3]:=91522
TestArray[3,4]:="Wilhelm-Busch-Str"
TestArray[4,1]:=4
TestArray[4,2]:="Meier"
TestArray[4,3]:=23552
TestArray[4,4]:="Marzipanstraße"


AnzahlZeilen:=TestArray[1].MaxIndex()
AnzahlSpalten:=TestArray[2].MaxIndex()

MsgBox AnzahlZeilen=%AnzahlZeilen%, AnzahlSpalten=%AnzahlSpalten%

gosub, ShowArray
; Funktion einfügen Sortiere nach Spalte N
gosub, ShowArray

ExitApp

ShowArray:
    loop, % AnzahlZeilen + 1
    {
        ;beginne mit Zeile 0
        Zeile := A_Index - 1
        loop, % AnzahlSpalten
        {
            Spalte:=A_Index
            gurk := TestArray[Zeile, A_Index]
            text.= "[" . Zeile . "|" . Spalte . "] = " . gurk . "`n`r"
        }
    }
    MsgBox %text%
    text:=""
return


strobo
Posts: 125
Joined: 30 Sep 2013, 15:24

Re: 2-dimensionales Array sortieren

23 Feb 2015, 09:21

Code: Select all

; http://rosettacode.org/wiki/Sorting_algorithms/Merge_sort#AutoHotkey_L
#NoEnv
 
Test := []
Loop 100 {
    Random n, 0, 999
    Test.Insert(n)
}
Result := MergeSort(Test)
Loop % Result.MaxIndex() {
    MsgBox, 1, , % Result[A_Index]
    IfMsgBox Cancel
        Break
}
Return
 
 
/*
    Function MergeSort
        Sorts an array by first recursively splitting it down to its
        individual elements and then merging those elements in their
        correct order.
 
    Parameters
        Array   The array to be sorted
 
    Returns
        The sorted array
*/
MergeSort(Array)
    {
        ; Return single element arrays
        If (! Array.HasKey(2))
            Return Array
 
        ; Split array into Left and Right halfs
        Left := [], Right := [], Middle := Array.MaxIndex() // 2
        Loop % Middle
            Right.Insert(Array.Remove(Middle-- + 1)), Left.Insert(Array.Remove(1))
        If (Array.MaxIndex())
            Right.Insert(Array.Remove(1))
 
        Left := MergeSort(Left), Right := MergeSort(Right)
 
        ; If all the Right values are greater than all the
        ; Left values, just append Right at the end of Left.
        If (Left[Left.MaxIndex()] <= Right[1]) { ; <------------
            Loop % Right.MaxIndex()
                Left.Insert(Right.Remove(1))
            Return Left
        }
        ; Loop until one of the arrays is empty
        While(Left.MaxIndex() and Right.MaxIndex())
            Left[1] <= Right[1] ? Array.Insert(Left.Remove(1)) ; <------------
                                : Array.Insert(Right.Remove(1))
 
        Loop % Left.MaxIndex()
            Array.Insert(Left.Remove(1))
 
        Loop % Right.MaxIndex()
            Array.Insert(Right.Remove(1))
 
        Return Array
    }
Ungetestet, aber im Falle des Funzens, müsste man an den mit ; <------------ markierten Zeilen nur eine Ebene tiefer ins Array gucken, z.B. Left[1] wird zu Left[1][key].
User avatar
Gurkentoepfer
Posts: 48
Joined: 24 Feb 2014, 14:52

Re: 2-dimensionales Array sortieren

23 Feb 2015, 10:12

hmmm, dazu müsste ich den Code verstehen können, was mir deutlich schwer fällt.

Alternativ könnte ich ja auch das ganze Array in ein Listview packen und die entsprechende Spalte sortieren,
leider sortiert er nur die eine Spalte und zieht nicht die anderen Spalteninhalte mit.

Code: Select all

loop, %AnzahlSpalten%
    Header .= TestArray[0,A_Index] . "|"

Gui, Add, ListView, r20 w200, %Header%
Loop, %AnzahlZeilen%
{
    zeile:=A_Index
    loop, %AnzahlSpalten%
    {
        Spalte:=A_Index
        col%A_Index% := TestArray[Zeile,Spalte]
    }
    LV_Add("", col1, col2, col3, col4, col5)
}
LV_ModifyCol()  ; Auto-size columns
Gui, Show

msgbox, sorting by column1
LV_ModifyCol(1, "sort") ; sort by first column
msgbox, sorting by column2
LV_ModifyCol(2, "sort Integer") ; sort by second column numerically
strobo
Posts: 125
Joined: 30 Sep 2013, 15:24

Re: 2-dimensionales Array sortieren

23 Feb 2015, 10:32

hmmm, dazu müsste ich den Code verstehen können
Nein Ja Jein Egal ... Forum-Compiler* übernimm!

*übersetzt (wie magisch) Problemstellungen in fix und fertigen code.
User avatar
Gurkentoepfer
Posts: 48
Joined: 24 Feb 2014, 14:52

Re: 2-dimensionales Array sortieren

23 Feb 2015, 13:31

Auf diese Art funktioniert es ... (Mit Hilfe von "sort") ...
  • 1. dazu muss die gewünschte Spalte nach vorne auf Array-Spalte 0 kopiert werden,
    2. das Array wird in Text umgewandelt,
    3. der Text sortiert,
    4. die Hilfs-Spalte 0 entfernt,
    5. die Überschrift wieder eingefügt werden.
Weiß nur nicht, ob es auch für große Tabellen (1.000-10.000 Zeilen) noch halbwegs flott funktioniert.
Bin daher nach wie vor noch an einer Sort-Funktion direkt im Array interessiert.

Und so sieht der Code aus ...

Code: Select all

; Array sortieren
;
; Tabelle:
;
; Nr | Name    | PLZ   | Straße
;----------------------------------------------
; 1  | Müller  | 90547 | Hubertusring
; 2  | Schmidt | 31852 | Steigenberger Str.
; 3  | Huber   | 91522 | Wilhelm-Busch-Str
; 4  | Meier   | 23552 | Marzipanstraße



TestArray:=[]
TestArray[0,1]:="Nr"
TestArray[0,2]:="Name"
TestArray[0,3]:="PLZ"
TestArray[0,4]:="Straße"
TestArray[1,1]:=1
TestArray[1,2]:="Müller"
TestArray[1,3]:=90547
TestArray[1,4]:="Hubertusring"
TestArray[2,1]:=2
TestArray[2,2]:="Schmidt"
TestArray[2,3]:=31852
TestArray[2,4]:="Steigenberger Str"
TestArray[3,1]:=3
TestArray[3,2]:="Huber"
TestArray[3,3]:=91522
TestArray[3,4]:="Wilhelm-Busch-Str"
TestArray[4,1]:=4
TestArray[4,2]:="Meier"
TestArray[4,3]:=23552
TestArray[4,4]:="Marzipanstraße"
TestArray[5,1]:=5
TestArray[5,2]:="Meyer"
TestArray[5,3]:=31811
TestArray[5,4]:="Birkenweg"


AnzahlZeilen:=TestArray.MaxIndex()
AnzahlSpalten:=TestArray[2].MaxIndex()

InputBox, SortCol,, Welche Spalte soll sortiert werden?

; Überschriftenzeile extrahieren
loop, % AnzahlSpalten
    Header .= TestArray[0,A_Index] . ";"
Header.= "`n"

; Array in TextVariable umwandeln ... Wert1;Wert2;...;`n
loop, % AnzahlZeilen
{
    Zeile := A_Index
    TestArray[Zeile,0] := TestArray[Zeile,SortCol]
    loop, % AnzahlSpalten + 1
    {
    Spalte := A_Index - 1
    text .= TestArray[Zeile,Spalte] . ";"
    }
    text .= "`n"
}
; Sortiere Text
sort, text

; Entferne erste Spalte
loop, Parse, text, `n
{
    StringGetPos, pos,A_LoopField,;
    pos+=1
    StringTrimLeft, gurk, A_LoopField, pos
    TextNew .= gurk . "`n"
}
; Füge Überschriftenzeile vorne an
Header .= TextNew

; Zeige Ergebnis
MsgBox %Header%

;~ FileAppend, %Header%, TextNew.csv
;~ run, TextNew.csv

 
just me
Posts: 7305
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: 2-dimensionales Array sortieren

23 Feb 2015, 19:34

Für eine eingebaute Sort Methode für Arrays müsstest Du lexikos begeistern, bisher hat das aber noch keiner geschafft.

Bei Deinem Skript frage ich mich, warum Du das Array veränderst, wenn Du das sortierte Array nicht zurückschreibst. Wenn es nur darum geht, eine sortierte Textausgabe zu erzeugen, gibt es für mich keinen Grund dafür.

Code: Select all

; Array sortieren
;
; Tabelle:
;
; Nr | Name    | PLZ   | Straße
;----------------------------------------------
; 1  | Müller  | 90547 | Hubertusring
; 2  | Schmidt | 31852 | Steigenberger Str.
; 3  | Huber   | 91522 | Wilhelm-Busch-Str
; 4  | Meier   | 23552 | Marzipanstraße



TestArray:=[]
TestArray[0,1]:="Nr"
TestArray[0,2]:="Name"
TestArray[0,3]:="PLZ"
TestArray[0,4]:="Straße"
TestArray[1,1]:=1
TestArray[1,2]:="Müller"
TestArray[1,3]:=90547
TestArray[1,4]:="Hubertusring"
TestArray[2,1]:=2
TestArray[2,2]:="Schmidt"
TestArray[2,3]:=31852
TestArray[2,4]:="Steigenberger Str"
TestArray[3,1]:=3
TestArray[3,2]:="Huber"
TestArray[3,3]:=91522
TestArray[3,4]:="Wilhelm-Busch-Str"
TestArray[4,1]:=4
TestArray[4,2]:="Meier"
TestArray[4,3]:=23552
TestArray[4,4]:="Marzipanstraße"
TestArray[5,1]:=5
TestArray[5,2]:="Meyer"
TestArray[5,3]:=31811
TestArray[5,4]:="Birkenweg"


AnzahlZeilen:=TestArray.MaxIndex()
AnzahlSpalten:=TestArray[2].MaxIndex()

InputBox, SortCol,, Welche Spalte soll sortiert werden (1 - 4)?

; Überschriftenzeile extrahieren
Header := ""
Loop, % AnzahlSpalten
    Header .= TestArray[0,A_Index] . ";"

; Array in TextVariable umwandeln ... Wert1;Wert2;...;`n
ArrayText := ""
Loop, % AnzahlZeilen
{
    Zeile := A_Index
    ArrayText .= TestArray[Zeile,SortCol] . ";"
    Loop, % AnzahlSpalten
        ArrayText .= TestArray[Zeile, A_Index] . ";"
    ArrayText .= "`n"
}
; Sortiere Text
Sort, ArrayText

; Entferne erste Spalte
ArrayText := RegExReplace(ArrayText, "`nm)^[^;]*;")

; Zeige Ergebnis
MsgBox %Header%`n%ArrayText%

;~ FileAppend, %Header%, TextNew.csv
;~ run, TextNew.csv
Ob der RegEx performanter als Deine Schleife ist, habe ich nicht 'gebenchmarkt'.

Aber, wenn Du deutsche Umlaute sortierst, kommst Du kaum um die Option CL herum, auch wenn das der Performance schadet. Für rein numerische Spalten kann die Option N das Ergebnis verbessern.

Return to “Ich brauche Hilfe”

Who is online

Users browsing this forum: No registered users and 2 guests