2010-02-24 15 views
10

Kiedy soritng tablica składa się z kombinacji łańcuchów, wartości zerowych i zer, otrzymuję wynik niepoprawnie jako wynikowy, wartości null wydają się sortowane tak, jakby były "zerowe" smyczki. Zrobiłem to (testowane na Firefox):Tablica sortowania javascript z mieszanymi ciągami znaków i wartościami pustymi

var arr1 = arr2 = [null, "b", "c", "d", null, "e", 0, "g", null, 0, "h", "i", "l", "m", "n", "o", "p", "ne", "nur", "nimbus"]; 

document.write("SORTED ARRAY:<br>"); 
arr1.sort(); 
arr1.forEach(function(val){document.write(val + "; ")}); 

a wynik jest:

posortowanej tablicy: 0; 0; b; do; re; mi; sol; h; ja; l; m; n; ne; chmura; zero; zero; zero; nur; o; p;

Czy masz pomysł, w jaki sposób uczynić wartość pustą być traktowane jako pusty ciąg podczas sortowania tablicy, tak aby stały się 1. w posortowanym arry wraz z zerami.

Dzięki!

+0

Czy potrzebujesz numerów posortowanych również przed ciągami? Porządek leksykograficzny to nie to samo co numeryczne. Jako przykład można podać zamawianie {100, 15} i {"100", "15"}. –

+0

@andras: Nie, tylko zera. –

Odpowiedz

12

to zrobi to, co chcesz przez przekształcenie wszystko do strun (w szczególności przekształcenie zerowy na pusty ciąg znaków) i pozwalając wbudowaną porównanie Łańcuch JavaScript jest wykonać pracę:

arr2.sort(function(a, b) 
{ 
    /* 
     We avoid reuse of arguments variables in a sort 
     comparison function because of a bug in IE <= 8. 
     See http://www.zachleat.com/web/array-sort/ 
    */ 
    var va = (a === null) ? "" : "" + a, 
     vb = (b === null) ? "" : "" + b; 

    return va > vb ? 1 : (va === vb ? 0 : -1); 
}); 
+0

+1 Dla Ternary Terseness –

+0

Nie uda się prawidłowo sortować, jeśli ma numery. Potrzebujesz więcej ternaries. –

+1

@andras Jeśli właściwie oznacza to, że 20 pojawia się przed 5 domyślny sort ma ten sam problem –

-1

Przeglądarka wykonuje polecenie null.toString(); ponieważ null jest obiektem, jest to w zasadzie Object.toString() ... które zwróci "null"

Przekaż parametr do sortowania, jako funkcję porównania [jeśli funkcja zwraca coś większego niż 0, b jest posortowana niższa niż]

funkcji byłoby w zasadzie być:

comparisonFunc = function(a, b) 
{ 
if((a === null) && (b === null)) return 0; //they're both null and equal 
else if((a === null) && (b != null)) return -1; //move a downwards 
else if((a != null) && (b === null)) return 1; //move b downwards 
else{ 
    //Lexicographical sorting goes here 
} 
} 
set.sort(comparisonFunc); 
-1

możesz przekazać Sortowanie sortfunction

array.sort(sortfunction) 

gdzie sortfunction robi to Compa Potrzebny ci rison (regularne sortowanie z wartościami pustymi, które są większe od innych)

1

Użyj niestandardowej funkcji porządkowania, która obsługuje w ten sposób wartości puste.

arr1.sort(function(a, b) { 
    if (a===null) a=''; 
    if (b===null) b=''; 

    if (''+a < ''+b) return -1; 
    if (''+a > ''+b) return 1; 

    return 0; 
}); 
+0

Ten pierwszy wiersz powinien oczywiście brzmieć: if (a === null) a = ''; – HBP

+0

@Hans Dzięki edytowane –

6
[null, "b", "c", "d", null, "e", 0, "g", null, 0, "h", "i", "l", "m", "n", "o", "p", "ne", "nur", "nimbus"].sort(function (a,b) { 
    return a === null ? -1 : b === null ? 1 : a.toString().localeCompare(b); 
}); 
+0

Ach tak, zapomniałem o 'localeCompare'. +1. –

3

Nie mogę jeszcze komentować odpowiedzi, ale chciałem podzielić się moim problemem na wypadek, gdyby ktoś inny używał rozwiązania Tims.

Tims rozwiązanie działało świetnie. JEDNAK ... to z przerwami wyrzuciłoby błąd "Oczekiwany numer". Całkowicie losowo.

Ten link wyjaśnia problem i obejście, które rozwiązały problem dla mnie ...

http://www.zachleat.com/web/array-sort/

Nadzieja ktoś oszczędza czas zmarnowałem debugowanie/googlowania!

+0

Ciekawe dzięki za udostępnienie, zaktualizowałem odpowiedzi Tim: http://stackoverflow.com/questions/2328562/javascript-sorting-array-of-mixed-strings-and-null-values/2328902#2328902 –

4

Natknąłem się na ten wątek szukając podobnej, szybkiej i brudnej odpowiedzi, ale nie dotknęło to, czego naprawdę potrzebowałem. "Jak leczyć wartości null", unoszą je na górze lub na dole itp.To właśnie wymyśliłem:

var list = [0, -1, 1, -1, 0, null, 1]; 

var sorter = function(direction){ 

    // returns a sort function which treats `null` as a special case, either 'always higher' (1) 
    // or 'always lower' (-1) 

    direction = direction || 1; 
    var up = direction > 0; 

    return function(a, b){ 

     var r = -1, 
      aa = a == null ? undefined : a, 
      bb = b == null ? undefined : b, 
      careabout = up ? aa : bb 
     ; 

     if(aa == bb){ 
      r = 0; 
     }else if(aa > bb || careabout == undefined){ 
      r = 1 
     } 
     return r; 

    } 

} 

var higher = [].concat(list.sort(sorter(1)));  
var lower = [].concat(list.sort(sorter(-1))); 

console.log(lower[0] === null, lower); 
console.log(higher[higher.length - 1] === null, higher); 

// then, something that sorts something in a direction can use that direction to 
// determine where the nulls end up. `list` above ranged from negative-one to one, 
// with mixed zero and null values in between. If we want to view that list 
// from highest value to descending, we'd want the nulls to be treated as 
// 'always lower' so they appear at the end of the list. 
// If we wanted to view the list from lowest value to highest value we'd want the 
// nulls to be treated as `higher-than-anything` so they would appear at the bottom 
// list. 

var sortThisArray = function(arr, direction){ 
    var s = sorter(direction); 
    return arr.sort(function(a,b){ 
     return direction * s(a,b) 
    }); 
} 

console.log(sortThisArray(list, 1)); 
console.log(sortThisArray(list, -1)); 
2

nie mogę dodać jeszcze komentarz do @ komentarzem Roberta, ale tutaj jest ekspansja na @ Robert, aby dodać wsparcie dla operacji:

[null, "b", "c", "d", null, "e", 0, undefined, "g", null, 0, "h", "i", true, "l", "m", undefined, "n", "o", "p", false, "ne", "nur", "nimbus"].sort(function (a,b) { 
    if (a === b) { return 0; } 
    if (a === null) { 
     return -1; 
    } else if (b === null) { 
     return 1; 
    } else if (typeof a === 'string') { 
     return a.localeCompare(b); 
    } else if (typeof a === 'number' || typeof a === 'boolean') { 
     if (a < b) return -1; 
     if (a > b) return 1; 
    } 
    return 0; 
}); 

również, zgodnie ze specyfikacją JS, undefineds zawsze uruchamia się na końcu tablicy ...

Powiązane problemy