2010-07-07 12 views
21

EDIT: Wie von kennytm unten und nach der Untersuchung selbst, nach der ECMA spec, wenn zwei Objekte als gleich in einer benutzerdefinierten Sortierung festgestellt werden, JavaScript ist nicht erforderlich, um diese beiden verlassen Objekte in der gleichen Reihenfolge. Sowohl Chrome als auch Opera sind die einzigen beiden großen Browser, die sich für nicht stabile Sortierungen entscheiden, andere enthalten Netscape 8, Kazehakaze, IceApe und einige andere. Das Chromium-Team hat diesen Fehler als "Arbeiten wie vorgesehen" markiert, damit er nicht "repariert" wird. Wenn Ihre Arrays in der ursprünglichen Reihenfolge bleiben sollen, wenn die Werte gleich sind, müssen Sie einen zusätzlichen Mechanismus (wie den oben genannten) verwenden. Rückgabe 0 beim Sortieren von Objekten ist effektiv bedeutungslos, also nicht stören. Oder verwenden Sie eine Bibliothek, die stabile Sortierung unterstützt, z. B. Underscore/Lodash.Sortierung eines Arrays von Objekten in Chrome


Ich habe gerade einen Bericht erhalten, dass ein Code, den ich geschrieben habe, in Chrome bricht. Ich habe es auf eine benutzerdefinierte Methode zurückverfolgt, mit der ich ein Array von Objekten sortiere. Ich bin wirklich versucht, dies einen Fehler zu nennen, aber ich bin mir nicht sicher, ob es das ist.

In allen anderen Browsern, wenn Sie ein Array von Objekten sortieren und zwei Objekte auf denselben Wert auflösen, bleibt ihre Reihenfolge im aktualisierten Array unverändert. In Chrome ist ihre Reihenfolge scheinbar zufällig. Führen Sie den folgenden Code in Chrome und einem beliebigen anderen Browser aus. Du solltest sehen was ich meine.

Ich habe zwei Fragen:

Zuerst war ich recht in der Annahme, dass, wenn Ihre benutzerdefinierten Sortierer zurück 0, dass die beiden verglichenen Artikel sollte in ihrer ursprünglichen Reihenfolge bleiben (ich habe das Gefühl, ich falsch war).

Zweitens gibt es eine gute Möglichkeit, dies zu beheben? Das einzige, was mir einfällt, ist das Hinzufügen einer automatisch inkrementierenden Zahl als Attribut zu jedem Element des Arrays vor dem Sortieren und dann die Verwendung dieses Wertes, wenn zwei Elemente sort die Auflösung mit demselben Wert vergleichen. Mit anderen Worten, nie wieder 0.

Hier ist der Beispielcode:

var x = [ 
{'a':2,'b':1}, 
{'a':1,'b':2}, 
{'a':1,'b':3}, 
{'a':1,'b':4}, 
{'a':1,'b':5}, 
{'a':1,'b':6}, 
{'a':0,'b':7}, 
] 

var customSort = function(a,b) { 
    if (a.a === b.a) return 0; 
    if (a.a > b.a) return 1; 
    return -1; 
}; 

console.log("before sorting"); 
for (var i = 0; i < x.length; i++) { 
    console.log(x[i].b); 
} 
x.sort(customSort); 

console.log("after sorting"); 
for (var i = 0; i < x.length; i++) { 
    console.log(x[i].b); 
} 

In allen anderen Browsern, was ich sehe, ist, dass nur das erste Element und das letzte Mitglied des Arrays verschobene bekommen (ich sehe 7,2,3,4,5,6,1), aber in Chrome sind die inneren Zahlen scheinbar zufällig.

[EDIT] Vielen Dank an alle, die geantwortet haben. Ich denke, dass "inkonsistent" nicht notwendigerweise bedeutet, dass es ein Fehler ist. Außerdem wollte ich nur darauf hinweisen, dass meine b Eigenschaft nur ein Beispiel war. Tatsächlich sortiere ich relativ breite Objekte auf einer von etwa 20 Tasten nach Benutzereingabe. Selbst das Nachverfolgen dessen, wonach der Benutzer zuletzt sortiert hat, wird das Problem der Zufälligkeit, die ich sehe, nicht lösen. Meine Arbeit-around wird wahrscheinlich eine enge Variante dieses seine (neuen Code markiert ist):

var x = [ 
{'a':2,'b':1}, 
{'a':1,'b':2}, 
{'a':1,'b':3}, 
{'a':1,'b':4}, 
{'a':1,'b':5}, 
{'a':1,'b':6}, 
{'a':0,'b':7}, 
]; 
var i; 

var customSort = function(a,b) { 
    if (a.a === b.a) return a.customSortKey > b.customSortKey ? 1 : -1; /*NEW CODE*/ 
    if (a.a > b.a) return 1; 
    return -1; 
}; 

console.log("before sorting"); 
for (i = 0; i < x.length; i++) {console.log(x[i].b);} 

for (i = 0; i < x.length; i++) {      /*NEW CODE*/ 
    x[i].customSortKey = i;       /*NEW CODE*/ 
}              /*NEW CODE*/ 
x.sort(customSort); 

console.log("after sorting"); 
for (i = 0; i < x.length; i++) {console.log(x[i].b);} 

Antwort

7

Die V8-Art ist nicht stabil, leider. Ich werde sehen, ob ich den Chrom-Bug darüber ausgraben kann.

+6

[V8 Ausgabe 90: V8 nicht stabil Art] (http: // Code .google.com/p/v8/issues/detail? id = 90 "V8 Fehler 90") – lawnsea

8

Mai werden Sie es schon wissen, aber Sie können einen Array verwenden, um auf mehreren Spalten zu sortieren und diesen Fehler zu vermeiden:

var customSort = function(a,b) { 
    return [a.a, a.b] > [b.a, b.b] ? 1:-1; 
} 
Verwandte Themen