Mam tablicę ciągów, które muszę sortować w JavaScript, ale bez rozróżniania wielkości liter. Jak to zrobić?
javascript
sorting
case-insensitive
Jérôme Verstrynge
źródło
źródło
return a.localeCompare(b, 'en', {'sensitivity': 'base'});
toLowerCase()
gdylocaleCompare
już to robi domyślnie w niektórych przypadkach. Możesz przeczytać więcej o parametrach, które należy przekazać tutaj: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…items.sort(new Intl.Collator('en').compare)
celu uzyskania lepszej wydajności. (Patrz MDN .)EDYCJA: Należy pamiętać, że pierwotnie napisałem to w celu zilustrowania techniki, a nie mając na uwadze wydajność. Bardziej kompaktowe rozwiązanie można znaleźć w odpowiedzi na @Ivan Krechetov.
źródło
toLowerCase
dwa razy na każdym ciągu; byłoby bardziej wydajne do przechowywania obniżonych wersji łańcucha w zmiennych..toLowerCase()
wiele razy dla każdego elementu w tablicy. Na przykład 45 wywołań funkcji porównywania podczas sortowania 10 pozycji w odwrotnej kolejności.var i = 0; ["z","y","x","w","v","u","t","s","r","q"].sort(function (a, b) {++i; return a.toLowerCase().localeCompare(b.toLowerCase());}); console.log("Calls to Compare: " + i); // i === 45
Czas wrócić do tego starego pytania.
Nie powinieneś używać rozwiązań opartych na
toLowerCase
. Są nieefektywne i po prostu nie działają w niektórych językach (na przykład tureckim). Wolę to:Sprawdź w dokumentacji kompatybilność przeglądarki i wszystko, co musisz wiedzieć o tej
sensitivity
opcji.źródło
źródło
return a === b ? 0 : a > b ? 1 : -1;
["111", "33"]
, możemy chcieć, aby zwrócił,["111", "33"]
ponieważ 1 występuje przed 3 w kolejności kodów znaków. Jednak funkcja w tej odpowiedzi zostanie zwrócona,["33", "111"]
ponieważ liczba33
jest mniejsza niż liczba111
."33" > "111" === true
i33 > 111 === false
. Działa zgodnie z przeznaczeniem.Możesz także użyć nowego
Intl.Collator().compare
, według MDN, jest to bardziej wydajne podczas sortowania tablic. Minusem jest to, że nie jest obsługiwany przez starsze przeglądarki. MDN stwierdza, że w ogóle nie jest obsługiwany w Safari. Musisz to zweryfikować, ponieważ stwierdza, żeIntl.Collator
jest obsługiwane.źródło
Jeśli chcesz zagwarantować tę samą kolejność niezależnie od kolejności elementów w tablicy wejściowej, oto stabilne sortowanie:
źródło
Normalizuj obudowę za
.sort()
pomocą.toLowerCase()
.źródło
Możesz także użyć operatora Elvisa:
Daje:
Metoda localeCompare jest prawdopodobnie w porządku ...
Uwaga: operator Elvisa jest skrótem od „operatora trójskładnikowego”, ponieważ w innym przypadku, zwykle z przypisaniem.
Jeśli spojrzysz na?: Z boku, wygląda jak Elvis ...
tzn. Zamiast:
możesz użyć:
tzn. gdy y jest prawdziwe, to zwróć 1 (dla przypisania do x), w przeciwnym razie zwróć 2 (dla przypisania do x).
źródło
x = y ? y : z
możesz to zrobićx = y ?: z
. JavaScript nie ma faktycznego operatora Elvisa, ale możesz używać gox = y || z
w podobny sposób.Inne odpowiedzi zakładają, że tablica zawiera łańcuchy. Moja metoda jest lepsza, ponieważ będzie działać, nawet jeśli tablica zawiera null, undefined lub inne nie łańcuchy.
null
Zostaną posortowane między „” i „nulk nulm”. Ale zawszeundefined
będą sortowane na końcu.źródło
(''+notdefined) === "undefined"
więc sortowałoby przed „z”Array.prototype.sort
: | ponieważ część o(''+notdefined) === "undefined"
naprawdę jest prawdziwa ... co oznacza, że jeśli odwrócisz -1 i 1 w funkcji sortowania, aby odwrócić kolejność, niezdefiniowane nadal będzie sortowane do końca. Należy również wziąć to pod uwagę, gdy używasz funkcji porównania poza kontekstem sortowania tablicowego (tak jak wtedy, gdy natrafiłem na to pytanie).Array.prototype.sort
definicji - jeszcze kilka komentarzy. Po pierwsze, nie ma potrzeby(''+a)
- ECMAScript wymagatoString()
wywołania elementów przed przekazaniem ich do CompareFn. Po drugie, fakt, żeignoreCase
zwraca się1
przy porównywaniu ciągów równych (w tym równych dla każdego przypadku) oznacza, że specyfikacja nie definiuje wyniku, jeśli istnieją zduplikowane wartości (myślę, że prawdopodobnie będzie w porządku tylko z kilkoma niepotrzebnymi zamianami, jak sądzę).undefined
jest to szczególny przypadek, który dla każdego x x <undefined i x> undefined są fałszywe . Toundefined
jest zawsze ostatnie, jest produktem ubocznym sortowania. Próbowałem zmienić ('' + a) na po prostu a, ale to się nie udaje. ja dostaćTypeError: a.toUpperCase is not a function
. Najwyraźniej nietoString
jest wywoływany przed wywołaniem funkcji porównawczej.undefined
porównania Fn nigdy nieWersja ES6:
["Foo", "bar"].sort((a, b) => a.localeCompare(b, 'en', { sensitivity: 'base' }))
Źródło: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/localeCompare
źródło
Na poparcie przyjętej odpowiedzi chciałbym dodać, że funkcja poniżej wydaje się zmieniać wartości w oryginalnej tablicy, która ma być sortowana, tak że nie tylko sortuje małe litery, ale wartości wielkich liter zostaną również zmienione na małe litery. Jest to dla mnie problem, ponieważ chociaż chcę widzieć Maryję obok Maryi, nie chcę, aby przypadek pierwszej wartości Mary został zmieniony na małe.
W moich eksperymentach następująca funkcja z zaakceptowanej odpowiedzi sortuje poprawnie, ale nie zmienia wartości.
źródło
Może to pomóc, jeśli masz problemy ze zrozumieniem:
http://jsfiddle.net/ianjamieson/wmxn2ram/1/
źródło
W powyższej funkcji, jeśli po prostu porównamy, gdy dwie małe litery a i b mają wartość, nie uzyskamy ładnego wyniku.
Przykład: jeśli tablica to [A, a, B, b, c, C, D, d, e, E] i korzystamy z powyższej funkcji, mamy dokładnie tę tablicę. Nic się nie zmieniło.
Aby uzyskać wynik [A, a, B, b, C, c, D, d, E, e], powinniśmy porównać ponownie, gdy dwie małe litery są równe:
źródło
Górną odpowiedź zapakowałem w polifill, aby móc wywoływać funkcję .sortIgnoreCase () na tablicach łańcuchów
źródło
Owiń swoje sznurki
/ /i
. Jest to prosty sposób na użycie wyrażenia regularnego do zignorowania obudowyźródło