Array in einer Tabelle sortieren

Beavis1311

Grünschnabel
Hallo,

ich habe eine kleines Problem und hoffe ihr könnt mir weiterhelfen :).

HTML:
<div>
     <table id="tabelle">
        <thead>
            <tr id="tabkopf">
                <th>Name</th>
                <th>Vorname</th>
                <th>Stra&szlig;e</th>
                <th>Hausnummer</th>
                <th>PLZ</th>
                <th>Ort</th>
                <th>E-Mail</th>
                <th>Webadresse</th>
                <th colspan="2">Aktion</th>
            </tr>
        </thead>
        <tbody id="tbody">
        </tbody>
     </table>
  </div>

das ist mein Tabellenkopf.
Die Tabelle wird über Javascript erzeugt. Aufgabe ist es, wenn ich auf einer bestimmten Kopfspalte gedrückt wird (bsp. Hausnummer), soll diese nummerisch bzw. alphabetisch sortiert werden. Mein Problem ist, woher weiß das "Programm" auf welcher Spalte ich draufklicke/was sortiert werden muss?

die tabelle wird durch einen Datensatz gefüllt:

var datensatz = [ [1,2,3,...],[],[],[],];

ich weiß es gibt den Befehl "array.sort()", weiß aber nicht wie ich ihn in diesen Fall anwenden muss. Könnt ihr mir bitte weiterhelfen/einen Ansatz schreiben. :)
 
und ohne fertige Skripte? :confused:

Javascript:
 var sortiert = [];
             for (i=0;i<datensatz.length;i++) {
            if (datensatz[i][a]>datensatz[i+1][a]){
                sortiert.push(datensatz[i+1]);
            } else{
                sortiert.push(datensatz[i]);
            }
          }

so oder so ähnlich?...und dann halt die "alte" Tabelle löschen(würde das funktionieren?)...
 
Zuletzt bearbeitet:
funktioniert jetzt soweit, nur hab ich noch ein Problem beim Hausnummervergleich...wenn ich die strings in integerwerte umwandle beachtet er nicht den Zusatz bei z.B. 12a oder 12b. Ich müsste also ein Stringvergleich machen und wenn Stellen fehlen diese mit Nullen ausfüllen(bsp. '12'<'4' wird zu '12'>'04' ). Wie könnte ich diese leeren Stellen jeweils an den kürzeren String ransetzen?
 
Sortieren kann sehr kompliziert sein. An dieser Stelle erscheint es mir richtig, etwas über Sortieralgorithmen zu erzählen.

Es gibt viele verschiedene Sortieralgorithmen. Grundsätzlich gibt es zwei verschiedene Arten: Vergleichsbasierte und nicht-vergleichsbasierte. Bei den vergleichsbasierten werden jeweils zwei Elemente untersucht und bei Bedarf vertauscht. Bei den nicht-vergleichsbasierten besteht zum Beispiel die Möglichkeit die Werte zu zerlegen, in Containern abzulegen und sie mit verschiedenen Gewichtungen neu zusammenzusetzen.

In diesem Wikipedia-Artikel sind einige Verfahren aufgelistet.

Für den Anfang eignet sich zum Beispiel Selectionsort. Dabei wird das Array in verschachtelten for-Schleifen durchlaufen. Die äußere Schleife durchläuft alle Elemente, die innere nur alle Elemente, die logisch nach dem aktuellen der äußeren Schleife stehen.

In der inneren Schleife wird so der kleinste Wert ermittelt und danach mit dem aktuellen Element der äußeren Schleife vertauscht. Damit steht das kleinste Element bereits an erster Stelle, es kann also beim 2. Element mit dem selben Verfahren vorgegangen werden. Hier findet sich das grafisch dargestellt und beschrieben.

Direkt mit deinem Beispiel arbeiten wäre schwieriger verständlich, daher vorerst an einem simplen Array:
Code:
var numbers = [7, 5, 11, 3, 9];
Jetzt lässt sich die erste Schleife anlegen. Außerdem ist bekannt, dass in jedem Durchlauf das kleinste Element rechts des aktuellen Elementes gefunden werden soll, daher muss eine Variable angelegt werden, die sich den Index dieses Elementes merkt. Anfangs wird davon ausgegangen, dass der aktuelle Index der kleinste ist:
Code:
var numbers = [7, 5, 11, 3, 9];

for(var startIndex = 0; startIndex < numbers.length; startIndex++)
{
    var smallestIndex = startIndex;

    // Platz für die 2. Schleife
}
Im nächsten Schritt muss die 2. Schleife angelegt werden. Diese beginnt rechts des aktuellen Elementes, also bei startIndex +1:
Code:
var numbers = [7, 5, 11, 3, 9];

for(var startIndex = 0; startIndex < numbers.length; startIndex++)
{
    var smallestIndex = startIndex;

    for(var currentIndex = startIndex + 1; currentIndex < numbers.length; currentIndex++)
    {
    }
}
Als nächstes muss ermittelt werden, ob das aktuelle Element der inneren Schleife kleiner oder für absteigende Sortierung größer als der bisher kleinste bekannte Index ist:
Code:
var numbers = [7, 5, 11, 3, 9];

for(var startIndex = 0; startIndex < numbers.length; startIndex++)
{
    var smallestIndex = startIndex;

    for(var currentIndex = startIndex + 1; currentIndex < numbers.length; currentIndex++)
    {
        if(numbers[currentIndex] < numbers[smallestIndex])
        {
            smallestIndex = currentIndex;
        }
    }
}
Am Ende eines jeden Durchlaufes der äußeren Schleife muss nun das kleinste bekannte Element mit dem aktuellen vertauscht werden, dafür ist eine temporäre Variable nötig:
Code:
var numbers = [7, 5, 11, 3, 9];

for(var startIndex = 0; startIndex < numbers.length; startIndex++)
{
    var smallestIndex = startIndex;

    for(var currentIndex = startIndex + 1; currentIndex < numbers.length; currentIndex++)
    {
        if(numbers[currentIndex] < numbers[smallestIndex])
        {
            smallestIndex = currentIndex;
        }
    }

    var temp = numbers[startIndex];
    numbers[startIndex] = numbers[smallestIndex];
    numbers[smallestIndex] = temp;
}
Man könnte noch prüfen ob sich startIndex überhaupt von smallestIndex unterscheidet. Wenn nicht, wäre das tauschen sinnlos.

Die Ausgabe des Arrays ergibt nun, dass es erfolgreich sortiert wurde:

Code:
Array [ 3, 5, 7, 9, 11 ]

Zu deinem Beispiel

Du benutzt nun kein simples Array voller Zahlen, sondern ein multidimensionales, von dem nur ein bestimmter Index des inneren Arrays interessant ist. Außerdem ergibt sich bei dir das Problem, dass du keine Zahlen sondern Strings sortieren möchtest. Auch die reinen Zahlen in deinem Datensatz sind Strings (ich gehe dabei von deiner Adressverwaltung aus).

Hier kommt es beim Vergleich zu einem kleinen Problem. Strings lassen sich genau so wie Integer (Zahlen) mit den Vergleichsoperatoren > und < vergleichen:
Code:
var compare = "A" < "B"; // true
var compare = "Giraffe" < "Affe"; // false
Bei Zahlen, die als String gespeichert sind, kommt es jedoch zu merkwürdigem Verhalten:
Code:
var compare = "7" < "15"; // false
Hier muss also mittels der parseInt-Funktion der String in einen Integer umgewandelt werden, um korrekte Ergebnisse zu erzielen.

Darum muss bei dem Vergleich deiner Daten jedes mal zusätzlich geprüft werden, ob es sich um Integer handelt oder nicht.

Aufrufen kannst du die Funktion ganz einfach durch deine th-Elemente im HTML Code. Eventlistener wären die saubere Lösung, jedoch hast du bisher ohne gearbeitet, daher mache ich das genau so wie du:
HTML:
<tr>
    <th onclick="sort(0)">Name</th>
    <th onclick="sort(1)">Vorname</th>
    <th onclick="sort(2)">Stra&szlig;e</th>
    <th onclick="sort(3)">Hausnummer</th>
    <th onclick="sort(4)">PLZ</th>
    <th onclick="sort(5)">Ort</th>
    <th onclick="sort(6)">E-Mail</th>
    <th onclick="sort(7)">Webadresse</th>
    <th colspan="2">Aktion</th>
</tr>
Die Zahl repräsentiert dabei den Index des betreffenden Elementes in deinem Array. Die Funktion dazu würde so aussehen:
Code:
function sort(thIndex)
{
    for(var startIndex = 0; startIndex < datensatz.length; startIndex++)
    {
        var smallestIndex = startIndex;

        for(var currentIndex = startIndex + 1; currentIndex < datensatz.length; currentIndex++)
        {
            if(datensatz[currentIndex][thIndex].toUpperCase() < datensatz[smallestIndex][thIndex].toUpperCase())
            {
                smallestIndex = currentIndex;
            }
        }

        var temp = datensatz[startIndex];
        datensatz[startIndex] = datensatz[smallestIndex];
        datensatz[smallestIndex] = temp;
    }
}
thIndex ist die aus dem Funktionsaufruf übergebene Zahl. Damit wird beim Vergleich einfach das entsprechende Element (zum Beispiel bei 0 auf die Vornamen) verwendet.

Damit lassen sich die Strings (Name, Vorname, Straße, Ort, E-Mail, Webadresse) bereits aufsteigend sortieren (und zwar mit einem Klick auf die entsprechende Spaltenüberschrift).

Das Problem mit den Integern lässt sich recht leicht beheben. Es wird einfach zu Beginn geprüft, ob in der entsprechenden Spalte Integer verwendet werden oder eben nicht. Dein möglicher Adresszusatz macht die Sache etwas schwieriger. Hausnummern fangen aber meines Wissens nach trotzdem mit einer Zahl an, daher reicht es, das erste Zeichen zu vergleichen.

An sich wird nur die durch parseInt konvertierte Variable mit der unkonvertierten geprüft und dementsprechend eine Variable true oder false gesetzt:
Code:
if(parseInt(datensatz[0][thIndex].substr(0, 1)) == datensatz[0][thIndex].substr(0, 1))
{
    var integer = true;
}
else
{
    var integer = false;
}

// Oder die kürzere Fassung mit dem ternären Operator:
var integer = (parseInt(datensatz[0][thIndex].substr(0, 1)) == datensatz[0][thIndex].substr(0, 1)) ? true : false;
In der inneren Schleife muss jetzt abgefragt werden, ob es sich um Integer handelt oder nicht und dementsprechend müssen geparste oder ungeparste Werte verglichen werden:
Code:
var integer = (parseInt(datensatz[0][thIndex].substr(0, 1)) == datensatz[0][thIndex].substr(0, 1)) ? true : false;

for(var startIndex = 0; startIndex < datensatz.length; startIndex++)
{
    var smallestIndex = startIndex;

    for(var currentIndex = startIndex + 1; currentIndex < datensatz.length; currentIndex++)
    {
        if(integer)
        {
            if(parseInt(datensatz[currentIndex][thIndex]) < parseInt(datensatz[smallestIndex][thIndex]))
            {
                smallestIndex = currentIndex;
            }
        }
        else
        {
            if(datensatz[currentIndex][thIndex].toUpperCase() < datensatz[smallestIndex][thIndex].toUpperCase())
            {
                smallestIndex = currentIndex;
            }
        }
    }

    var temp = datensatz[startIndex];
    datensatz[startIndex] = datensatz[smallestIndex];
    datensatz[smallestIndex] = temp;
}
Jetzt könnte man noch einfügen, dass bei einem erneuten Klick auf eine Spaltenüberschrift die Sortierung von aufsteigend zu absteigend wechselt. Außerdem müssen gleiche Zahlen mit unterschiedlichen Zusätzen wie Strings behandelt werden (z. B. 15a und 15b. Das lasse ich zum herumtesten mal mit einem unkommentierten Beispiel stehen:
Code:
var sortIndex = -1;
var asc = true;

function sort(thIndex)
{
    if(thIndex != sortIndex)
    {
        sortIndex = thIndex;
        asc = true;
    }
    else
    {
        asc = (!asc) ? true : false;
    }

    var integer = (parseInt(datensatz[0][thIndex].substr(0, 1)) == datensatz[0][thIndex].substr(0, 1)) ? true : false;

    for(var startIndex = 0; startIndex < datensatz.length; startIndex++)
    {
        var smallestIndex = startIndex;

        for(var currentIndex = startIndex + 1; currentIndex < datensatz.length; currentIndex++)
        {
            if(integer)
            {
                if
                (
                    (asc && parseInt(datensatz[currentIndex][thIndex]) < parseInt(datensatz[smallestIndex][thIndex])) ||
                    (!asc && parseInt(datensatz[currentIndex][thIndex]) > parseInt(datensatz[smallestIndex][thIndex]))
                )
                {
                    smallestIndex = currentIndex;
                }
                else if(parseInt(datensatz[currentIndex][thIndex]) == parseInt(datensatz[smallestIndex][thIndex]))
                {
                    if
                    (
                        (asc && datensatz[currentIndex][thIndex].toUpperCase() < datensatz[smallestIndex][thIndex].toUpperCase()) ||
                        (!asc && datensatz[currentIndex][thIndex].toUpperCase() > datensatz[smallestIndex][thIndex].toUpperCase())
                    )
                    {
                        smallestIndex = currentIndex;
                    }
                }
            }
            else
            {
                if
                (
                    (asc && datensatz[currentIndex][thIndex].toUpperCase() < datensatz[smallestIndex][thIndex].toUpperCase()) ||
                    (!asc && datensatz[currentIndex][thIndex].toUpperCase() > datensatz[smallestIndex][thIndex].toUpperCase())
                )
                {
                    smallestIndex = currentIndex;
                }
            }
        }

        var temp = datensatz[startIndex];
        datensatz[startIndex] = datensatz[smallestIndex];
        datensatz[smallestIndex] = temp;
    }

    tabneuzeichnen(); // Funktion von Beavis1311
}
Schleifen debuggen kann sehr nervig sein. Wenn du Fragen hast oder auf Probleme stößt lass es uns einfach wissen, wir können dir sicher helfen.

Bitte auch Bescheid geben, falls ich einen Fehler eingebaut habe.
 
Zurück