2012-01-25 21 views

Odpowiedz

265

W (prawie :) one-liner

["Foo", "bar"].sort(function (a, b) { 
    return a.toLowerCase().localeCompare(b.toLowerCase()); 
}); 

co skutkuje

[ 'bar', 'Foo' ] 

podczas

["Foo", "bar"].sort(); 

wyników w

[ 'Foo', 'bar' ] 
+7

Należy pamiętać, że zaawansowane opcje localeCompare nie są jeszcze obsługiwane na wszystkich platformach/przeglądarkach. Wiem, że nie są używane w tym przykładzie, ale po prostu chciałem dodać dla jasności. [Zobacz MDN po więcej informacji] (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/localeCompare) –

+50

Jeśli zamierzasz włączyć localeCompare(), możesz po prostu używaj * jego * zdolności do rozróżniania małych i wielkich liter, np .: 'return a.localeCompare (b, 'en', {'sensitivity': 'base'});' –

+1

+1 dla nie wywoływania 'toLowerCase()' kiedy 'localeCompare' robi to już domyślnie w niektórych przypadkach. Możesz przeczytać więcej na temat parametrów, które należy przekazać tutaj: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/localeCompare#Parameters – Milimetric

4

Normalizacja obudowy w .sort() z .toLowerCase().

21
arr.sort(function(a,b) { 
    a = a.toLowerCase(); 
    b = b.toLowerCase(); 
    if (a == b) return 0; 
    if (a > b) return 1; 
    return -1; 
}); 
+0

lub "return a === b? 0: a> b? 1: -1; ' –

55
myArray.sort(
    function(a, b) { 
    if (a.toLowerCase() < b.toLowerCase()) return -1; 
    if (a.toLowerCase() > b.toLowerCase()) return 1; 
    return 0; 
    } 
); 

EDIT: Należy pamiętać, że pierwotnie napisałem to, aby zilustrować technikę zamiast wydajność w umyśle. Proszę również zapoznać się z odpowiedzią @Ivan Krechetov dla bardziej zwartego rozwiązania.

+3

To może wywołać' toLowerCase' dwa razy na każdym ciągu; byłoby bardziej skuteczne przechowywanie obniżonych wersji łańcucha w zmiennych. – Jacob

+0

Prawda i dzięki. Napisałem to z myślą o jasności, a nie wydajności. Chyba powinienem to zauważyć. –

+1

@Jacob Aby być uczciwym, zaakceptowana odpowiedź ma ten sam podstawowy problem: może wywołać '.toLowerCase()' wiele razy dla każdego elementu w tablicy. Na przykład 45 wywołań funkcji porównywania podczas sortowania 10 elementów w odwrotnej kolejności. 'var i = 0; ["z", "y", "x", "w", "v", "u", "t", "s", "r", "q"]. sort (funkcja (a, b) {++ i; return a.toLowerCase(). localeCompare (b.toLowerCase());}); console.log ("Połączenia do porównania:" + i); // i === 45' – nothingisnecessary

8

Jeśli chcesz, aby zapewnić taką samą kolejność niezależnie od kolejności elementów tablicy wejściowej, tutaj jest stable Sortowanie:

myArray.sort(function(a, b) { 
    /* Storing case insensitive comparison */ 
    var comparison = a.toLowerCase().localeCompare(b.toLowerCase()); 
    /* If strings are equal in case insensitive comparison */ 
    if (comparison === 0) { 
     /* Return case sensitive comparison instead */ 
     return a.localeCompare(b); 
    } 
    /* Otherwise return result */ 
    return comparison; 
}); 
3

Można również użyć operatora Elvis:

arr = ['Bob', 'charley', 'fudge', 'Fudge', 'biscuit']; 
arr.sort(function(s1, s2){ 
    var l=s1.toLowerCase(), m=s2.toLowerCase(); 
    return l===m?0:l>m?1:-1; 
}); 
console.log(arr); 

daje :

biscuit,Bob,charley,fudge,Fudge 

Sposób localeCompare jest chyba w porządku, chociaż ...

Uwaga: Operator Elvis jest krótką formą "operatora trójskładnikowego", jeśli jeszcze, zwykle z przydziałem.
Jeśli spojrzeć na: bokiem, wygląda jak Elvis ...
czyli zamiast:

if (y) { 
    x = 1; 
} else { 
    x = 2; 
} 

można użyć:

x = y?1:2; 

tj gdy y jest prawdą, a następnie return 1 (dla przypisania do x), w przeciwnym razie zwraca 2 (dla przypisania do x).

0

To może pomóc, jeśli starali się zrozumieć:

var array = ["sort", "Me", "alphabetically", "But", "Ignore", "case"]; 
console.log('Unordered array ---', array, '------------'); 

array.sort(function(a,b) { 
    a = a.toLowerCase(); 
    b = b.toLowerCase(); 
    console.log("Compare '" + a + "' and '" + b + "'"); 

    if(a == b) { 
     console.log('Comparison result, 0 --- leave as is '); 
     return 0; 
    } 
    if(a > b) { 
     console.log('Comparison result, 1 --- move '+b+' to before '+a+' '); 
     return 1; 
    } 
    console.log('Comparison result, -1 --- move '+a+' to before '+b+' '); 
    return -1; 


}); 

console.log('Ordered array ---', array, '------------'); 


// return logic 

/*** 
If compareFunction(a, b) is less than 0, sort a to a lower index than b, i.e. a comes first. 
If compareFunction(a, b) returns 0, leave a and b unchanged with respect to each other, but sorted with respect to all different elements. Note: the ECMAscript standard does not guarantee this behaviour, and thus not all browsers (e.g. Mozilla versions dating back to at least 2003) respect this. 
If compareFunction(a, b) is greater than 0, sort b to a lower index than a. 
***/ 

http://jsfiddle.net/ianjamieson/wmxn2ram/1/

0
arr.sort(function(a,b) { 
    a = a.toLowerCase(); 
    b = b.toLowerCase(); 
    if(a == b) return 0; 
    if(a > b) return 1; 
    return -1; 
}); 

W powyższej funkcji, jeśli po prostu porównać gdy małe litery dwie wartości aib, nie będziemy mieli ładny wynik.

Przykład, jeśli tablica to [A, a, B, b, c, C, D, d, e, E] i używamy powyższej funkcji, mamy dokładnie tą tablicę. Nic nie zmienia.

Aby uzyskać wynik w [A, A, B, B, C, C, D, D, E, k], to należy porównać ponownie po dwóch dolna wartość przypadku jest równa:

function caseInsensitiveComparator(valueA, valueB) { 
    var valueALowerCase = valueA.toLowerCase(); 
    var valueBLowerCase = valueB.toLowerCase(); 

    if (valueALowerCase < valueBLowerCase) { 
     return -1; 
    } else if (valueALowerCase > valueBLowerCase) { 
     return 1; 
    } else { //valueALowerCase === valueBLowerCase 
     if (valueA < valueB) { 
      return -1; 
     } else if (valueA > valueB) { 
      return 1; 
     } else { 
      return 0; 
     } 
    } 
} 
0

Owiń swoje struny w / /i. Jest to łatwy sposób użycia regex do ignorowania obudowy

1

Pozostałe odpowiedzi zakładają, że tablica zawiera ciągi. Moja metoda jest lepsza, ponieważ zadziała, nawet jeśli tablica zawiera wartości null, undefined lub inne nie-łańcuchowe.

var notdefined; 
var myarray = ['a', 'c', null, notdefined, 'nulk', 'BYE', 'nulm']; 

myarray.sort(ignoreCase); 

alert(JSON.stringify(myarray)); // show the result 

function ignoreCase(a,b) { 
    return (''+a).toUpperCase() < (''+b).toUpperCase() ? -1 : 1; 
} 

The null zostaną posortowane między '' i 'nulk nulm'. Jednak undefined zawsze będzie sortowany jako ostatni.

+0

' ('' + notdefined) === "undefined" ', więc będzie sortować wcześniej" z " – MattW

+0

@MattW Nie masz racji. zobacz https://jsfiddle.net/qrw0uy3r/ –

+0

Zgadnij, że powinienem znaleźć definicję 'Array.prototype.sort': | ponieważ część dotycząca '('' + notdefined) ===" undefined "' * naprawdę jest * true ... co oznacza, że ​​jeśli odwrócisz -1 i 1 w funkcji sortowania, aby odwrócić kolejność, undefined nadal sortuje do koniec. Trzeba go również wziąć pod uwagę przy korzystaniu z funkcji porównania poza kontekstem sortowania w tablicy (tak jak wtedy, gdy natknąłem się na to pytanie). – MattW

3

Możesz także użyć nowego Intl.Collator().compare, na MDN to more efficient podczas sortowania tablic. Minusem jest to, że nie jest obsługiwany przez starsze przeglądarki. MDN stwierdza, że ​​nie jest w ogóle obsługiwane w Safari. Należy go zweryfikować, ponieważ stwierdza, że ​​obsługiwana jest wersja Intl.Collator.

When comparing large numbers of strings, such as in sorting large arrays, it is better to create an Intl.Collator object and use the function provided by its compare property

["Foo", "bar"].sort(Intl.Collator().compare); //["bar", "Foo"] 
+0

Przykręć stare przeglądarki; Używam tego. –

0

ja owinięty górna odpowiedź w PolyFill więc mogę zadzwonić .sortIgnoreCase() na tablicach smyczkowych

// Array.sortIgnoreCase() polyfill 
if (!Array.prototype.sortIgnoreCase) { 
    Array.prototype.sortIgnoreCase = function() { 
     return this.sort(function (a, b) { 
      return a.toLowerCase().localeCompare(b.toLowerCase()); 
     }); 
    }; 
} 
1

To jest czas, aby ponownie ten stary pytanie.

Nie powinieneś używać rozwiązań polegających na toLowerCase. Są one nieefektywne i po prostu nie działają w niektórych językach (na przykład turecki). Wolę to:

['Foo', 'bar'].sort((a, b) => a.localeCompare(b, undefined, {sensitivity: 'base'})) 

Sprawdź documentation kompatybilności przeglądarki i wszystko, co trzeba wiedzieć na temat opcji sensitivity.

Powiązane problemy