Wie kann ich Arrays mithilfe von DOM-Methoden zuverlässig partitionieren?

8

UP-FRONT HINWEIS: Ich verwende hier keine jQuery oder eine andere Bibliothek, weil ich verstehen möchte, was ich geschrieben habe und warum es funktioniert (oder nicht), also bitte nicht Beantworten Sie dies mit Bibliotheken oder Plugins für Bibliotheken. Ich habe nichts gegen Bibliotheken, aber für dieses Projekt sind sie meinen Programmzielen feindlich.

Das sagte ...

Über Ссылка habe ich eine Spaltensortierung mit DOM-Funktionen hinzugefügt, die ich selbst geschrieben habe. Das Problem ist, dass es zwar für den einfachen Fall der Alphabetisierung von Zeichenfolgen funktioniert, aber die Ergebnisse in den Browsern inkonsistent sind, wenn ich versuche, nach mehreren numerischen Begriffen zu sortieren - in der Tat, wenn ich versuche, mit zwei Untersortierungen zu sortieren / p>

Wenn Sie beispielsweise in Safari oder Firefox unter OS X einige Male auf "Decimal RGB" klicken, erhalten Sie die gewünschten Ergebnisse. Machen Sie dasselbe in Chrome oder Opera (wieder OS X) und Sie erhalten sehr unterschiedliche Ergebnisse. Ja, Safari und Chrome weichen hier ab.

Hier ist ein Ausschnitt der JS, die ich für die RGB-Sortierung verwende:

%Vor%

( sorter ist das Array, das ich sortieren möchte.)

Die Sortierung erfolgt in der Tradition einer anderen StackOverflow-Frage " Wie sortiert man ein multidimensionales Array nach mehreren Spalten in JavaScript? " und sein beste Antwort Aber die Ergebnisse sind nicht das, was ich in zwei der vier Browser erwartet habe, die ich anfangs ausprobiert habe.

Ich sortiere (ha!), dass dies mit Array-Sortierungen zu tun hat, die "instabil" sind - hier kein Argument! - Aber was ich nicht weiß, ist, wie man es auf eine konsistente, zuverlässige Art und Weise überwinden kann. Ich könnte wirklich eine Hilfe nutzen, um das Problem zu verstehen und die Lösung oder zumindest eine generische Beschreibung der Lösung zu sehen.

Mir ist klar, dass es wahrscheinlich sechs Millionen Möglichkeiten gibt, den Rest des JS zu optimieren (ja, ich habe ein globales verwendet). Ich bin immer noch ein JS Neuling und versuche das durch Übung zu korrigieren. Im Moment ist es die Array-Sortierung, die mich verwirrt, und ich könnte etwas Hilfe mit diesem Teil des Skripts verwenden, bevor ich den Code an anderer Stelle auffrische. Vielen Dank im Voraus!

AKTUALISIEREN

Zusätzlich zu den großartigen Erklärungen und Vorschlägen unten habe ich eine Linie zu einer noch kompakteren Lösung bekommen:

%Vor%

Obwohl ich es noch nicht ganz verstanden habe, glaube ich, dass ich anfange, seine Umrisse zu erfassen und es ist, was ich jetzt benutze. Danke an alle für Ihre Hilfe!

    
Eric A. Meyer 25.05.2012, 17:40
quelle

2 Antworten

5

OK. Wie Sie herausgefunden haben, besteht Ihr Problem darin, dass die Standard-JavaScript-Sortierung nicht garantiert stable ist. Genauer gesagt denke ich, dass es in deinem Kopf so funktioniert: Ich sortiere nach Blau, und wenn ich nach Grün sortiere, wird der Sortierer Einträge in meinem Array nur nach oben und unten verschieben, aber sie nach Blau geordnet halten. Leider ist das Universum nicht so bequem angeordnet; Die eingebaute JS-Sortierung erlaubt die Sortierung nach Belieben. Insbesondere ist es erlaubt, den Inhalt des Arrays einfach in einen großen Bucket zu werfen und sie dann nach dem zu sortieren, was Sie gefragt haben, vollständig ignorierend wie es vorher arrangiert wurde, und es sieht zumindest so aus Einige Browser tun genau das.

Dafür gibt es verschiedene Möglichkeiten, für Ihr spezielles Beispiel. Erstens könnten Sie die Sortierung immer noch in drei separaten Aufrufen durchführen, aber stellen Sie sicher, dass diese Aufrufe die Sortierung stabil ausführen. Das würde bedeuten, dass Sie nach der Blene-Sortierung stabil nach Grün sortieren würden, und das würde Ihnen ein nach Grün sortiertes Array geben in der Reihenfolge der Bläue (genau das, wonach du suchst). Meine Sortiertabelle führt dies durch die Implementierung einer "Shaker-Sortierung" oder "Cocktail-Sortierung" -Methode (http://en.wikipedia.org/wiki/Cocktail_sort) durch; Im Wesentlichen läuft diese Art der Sortierung durch die Liste und verschiebt die Elemente auf und ab. (Insbesondere, was es tut nicht ist, werfen Sie einfach alle Listenelemente in einen Eimer und ziehen Sie sie wieder heraus.) Es gibt eine nette kleine Grafik auf dem Wikipedia-Artikel. Dies bedeutet, dass "Subsorts" sortiert bleiben - d. H. Dass die Sortierung stabil ist und Ihnen das geben wird, was Sie wollen.

Aber für diesen Anwendungsfall würde ich mir keine Sorgen darum machen, die Sortierung in drei verschiedenen Aufrufen durchzuführen und sicherzustellen, dass sie stabil sind und all das; stattdessen würde ich die ganze Sortierung auf einmal erledigen. Wir können uns einen RGB-Farbindikator (255, 192, 80) als eine große Zahl in einer seltsamen Basis vorstellen: Um zu viel Mathematik zu vermeiden, stellen Sie sich die Basis 1000 vor (wenn dieser Satz keinen Sinn ergibt, ignorieren Sie ihn; davon, dass das gesamte rgb-Attribut in eine Zahl umgewandelt wird, die alles umfasst, ein bisschen so, wie CSS Präzedenzfälle in der Kaskade berechnet). Also könnte diese Zahl als tatsächlich 255,192,080 angesehen werden. Wenn Sie diese Zahl für jede Ihrer Zeilen berechnen und dann nach dieser Zahl sortieren, wird alles funktionieren, und Sie müssen die Sortierung nur noch einmal durchführen: Anstatt also drei Sortierungen zu machen, können Sie einen machen: sorter.sort(function(a,b) { return (a.red*1000000 + a.green*1000 + a.blue) - (b.red*1000000 + b.green*1000 + b.blue) } und es wird alles funktionieren.

Technisch gesehen ist das ein wenig ineffizient, weil Sie jedes Mal, wenn Ihre Sortierfunktion aufgerufen wird, diese "1000er-Basisnummer" berechnen müssen, was (wahrscheinlich) mehr als einmal pro Zeile sein kann. Wenn das ein großes Problem ist (was Sie durch Benchmarking herausfinden können), dann können Sie eine Schwartzsche Transformation verwenden (Entschuldigung für alle Schlagworte hier): im Grunde erarbeiten Sie die Basis-1000-Nummer Geben Sie für jede Zeile einmal alle in eine Liste ein, sortieren Sie die Liste und gehen Sie dann durch die sortierte Liste. Erstellen Sie also eine Liste, die wie [ [255192080, <table row 1>], [255255255, <table row 2>], [192000000, <table row 3>] ] aussieht, sortieren Sie diese Liste (mit einer Funktion wie mylist.sort(function(a,b) { return a[0]-b[0]; }) ) und gehen Sie dann durch diese Liste und fügen Sie jedem der s eine Child auf die Tabelle hinzu, die die gesamte Tabelle in der richtigen Reihenfolge sortiert. Du brauchst diesen letzten Absatz wahrscheinlich nicht für die Tabelle, die du hast, aber es könnte nützlich sein und es ist sicherlich nicht schaden, über diesen Trick Bescheid zu wissen, den sorttable.js ebenfalls verwendet.

    
sil 25.05.2012, 18:17
quelle
1

Ich würde dieses Problem auf andere Weise angehen. Anscheinend versuchen Sie, alle Daten zu rekonstruieren, indem Sie sie aus dem Markup extrahieren, was eine gefährliche Aufgabe sein kann. Ein einfacherer Ansatz bestünde darin, alle Daten, die auf der Seite gerendert werden sollen, in einem Format darzustellen, das Ihre Programme von Anfang an verstehen, und dann das Markup beim Laden der Seite und bei jeder nachfolgenden Sortierung einfach neu zu generieren.

>

Zum Beispiel:

%Vor%

Auf diese Weise können Sie Sortierungen für dieses Array auf beliebige Weise ausführen, und Sie versuchen nicht, Daten aus dem Markup herauszureißen, zu teilen und neu zuzuordnen.

Aber wirklich, es scheint, dass Sie vielleicht auf den Sortierfunktionen hängen. Das Ausführen mehrerer Sortierungen nacheinander führt zu unbeabsichtigten Ergebnissen. Sie müssen eine einzige Sortierfunktion ausführen, die die nächste 'Spalte' vergleicht, falls der vorherige gleich ist. Eine RGB-Sortierung könnte folgendermaßen aussehen:

%Vor%

Also würden zwei Farben mit übereinstimmenden r- und g-Werten für Gleichheit auf dem b-Wert zurückkehren, was genau das ist, wonach Sie suchen.

Dann können Sie die Sortierung anwenden:

%Vor%

.. und schließlich durchlaufen Sie dieses Array, um das Markup in der Tabelle neu zu erstellen.

Ich hoffe, es hilft, Sir -

    
keekerdc 25.05.2012 18:21
quelle

Tags und Links