Mam listę obiektów, które chcę sortować na podstawie pola attr
typu string. Próbowałem użyć-
list.sort(function (a, b) {
return a.attr - b.attr
})
ale okazało się, że -
nie działa z łańcuchami w JavaScript. Jak mogę posortować listę obiektów na podstawie atrybutu z ciągiem znaków?
javascript
string
airportyh
źródło
źródło
JavaScript case insensitive string comparison
na stackoverflow.com/questions/2140627/…Javascript : remove accents/diacritics in strings
na stackoverflow.com/questions/990904/...Odpowiedzi:
Użyj
String.prototype.localeCompare
na przykład:Zmuszamy a.attr jako ciąg znaków, aby uniknąć wyjątków.
localeCompare
jest obsługiwany od wersji Internet Explorer 6 i Firefox 1. Możesz także zobaczyć następujący kod, który nie przestrzega ustawień regionalnych:źródło
localeCompare()
nie napotyka tego problemu, ale nie rozumie liczb, więc otrzymasz [„1”, „10”, „2”] jak przy sortowaniu porównań w większości języków. jeśli chcesz sortować dla interfejsu użytkownika, zajrzyj do algorytmu sortowania alphanum / natural stackoverflow.com/questions/4340227/... lub stackoverflow.com/questions/4321829/...localeCompare()
jest obsługiwany tylko w nowoczesnych przeglądarkach: IE11 + w momencie pisania, patrz developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…localeCompare()
cofanie się o wiele wersji, ale nie obsługuje określania ustawień regionalnych aż do wersji 11. Zwróć też uwagę na pytania, z którymi łączył się Dead.Rabit.Zaktualizowana odpowiedź (październik 2014 r.)
Byłem naprawdę zirytowany tą naturalną kolejnością sortowania ciągów, więc poświęciłem sporo czasu na zbadanie tego problemu. Mam nadzieję, że to pomoże.
Krótko mówiąc
localeCompare()
obsługa postaci jest kiepska, po prostu jej używaj. Jak wskazanoShog9
, odpowiedź na twoje pytanie brzmi:Błędy znalezione we wszystkich niestandardowych implementacjach javascript „porządek sortowania ciągów znaków”
Istnieje całkiem sporo niestandardowych implementacji, które starają się porównywać ciągi bardziej precyzyjnie zwane „porządkiem sortowania ciągów naturalnych”
Kiedy „bawiłem się” tymi implementacjami, zawsze zauważyłem jakiś dziwny wybór „naturalnego porządku sortowania”, a raczej błędy (lub pominięcia w najlepszych przypadkach).
Zazwyczaj znaki specjalne (spacja, myślnik, znak ampersand, nawiasy itd.) Nie są przetwarzane poprawnie.
Zauważysz, że pojawiają się one pomieszane w różnych miejscach, zwykle mogą to być:
Gdyby można było oczekiwać, że wszystkie znaki specjalne zostaną „zgrupowane” razem w jednym miejscu, może z wyjątkiem spacji specjalnej postaci (która zawsze byłaby pierwszą postacią). To znaczy albo wszystkie przed cyframi, albo wszystkie między cyframi i literami (małe i wielkie litery są „razem” jedna po drugiej) lub wszystkie po literach.
Doszedłem do wniosku, że wszystkie nie zapewniają spójnego porządku, gdy zaczynam dodawać ledwo niezwykłe znaki (tj. Znaki z znakami diakrytycznymi lub znakami takimi jak myślnik, wykrzyknik i tak dalej).
Badanie niestandardowych implementacji:
Natural Compare Lite
https://github.com/litejs/natural-compare-lite : Nie udaje się podczas sortowania konsekwentnie https://github.com/litejs/natural-compare-lite/issues/1 i http://jsbin.com/bevututodavi/ 1 / edit? Js, konsola , sortowanie podstawowych znaków łacińskich http://jsbin.com/bevututodavi/5/edit?js,consoleNatural Sort
https://github.com/javve/natural-sort : Konsekwentnie kończy się sortowaniem, patrz problem https://github.com/javve/natural-sort/issues/7 i zobacz podstawowe łacińskie znaki sortujące http: // jsbin. com / cipimosedoqe / 3 / edit? js, consoleJavascript Natural Sort
https://github.com/overset/javascript-natural-sort : wydaje się raczej zaniedbany od lutego 2012 r., Nie udaje się sortować konsekwentnie, patrz problem https://github.com/overset/javascript-natural-sort/issues/16Alphanum
http://www.davekoelle.com/files/alphanum.js , Nie udaje się konsekwentnie sortować , patrz http://jsbin.com/tuminoxifuyo/1/edit?js,consoleNatywne implementacje przeglądarki „naturalny porządek sortowania ciągów” za pośrednictwem
localeCompare()
localeCompare()
najstarsza implementacja (bez argumentów ustawień narodowych i opcji) jest obsługiwana przez IE6 +, patrz http://msdn.microsoft.com/en-us/library/ie/s4esdbwz(v=vs.94).aspx (przewiń w dół do localeCompare ( ) metoda). WbudowanalocaleCompare()
metoda znacznie lepiej radzi sobie z sortowaniem, nawet znaków międzynarodowych i specjalnych. Jedynym problemem związanym z tąlocaleCompare()
metodą jest to, że „użyte ustawienia regionalne i porządek sortowania są całkowicie zależne od implementacji”. Innymi słowy, podczas korzystania z localeCompare, takiego jak stringOne.localeCompare (stringTwo): Firefox, Safari, Chrome i IE mają inną kolejność sortowania dla ciągów.Badanie implementacji natywnych dla przeglądarki:
Trudność w „naturalnym porządku sortowania ciągów”
Wdrożenie solidnego algorytmu (co oznacza: spójny, ale także obejmujący szeroki zakres znaków) jest bardzo trudnym zadaniem. UTF8 zawiera ponad 2000 znaków i obejmuje ponad 120 skryptów (języków) . Wreszcie, istnieje pewna specyfikacja dla tych zadań, nazywa się to „Algorytm sortowania Unicode”, który można znaleźć na stronie http://www.unicode.org/reports/tr10/ . Więcej informacji na ten temat można znaleźć w tym pytaniu: /software/257286/is-there-any-language-agnostic-specification-for-string-natural-sorting-order
Ostateczna konkluzja
Biorąc pod uwagę obecny poziom wsparcia zapewnianego przez niestandardowe implementacje javascript, z którymi się zetknąłem, prawdopodobnie nigdy nie zobaczymy, żeby cokolwiek zbliżyło się do obsługi wszystkich tych znaków i skryptów (języków). Dlatego wolałbym używać natywnej metody localeCompare () przeglądarki. Tak, ma tę wadę, że jest niespójna w różnych przeglądarkach, ale podstawowe testy pokazują, że obejmuje znacznie szerszy zakres znaków, umożliwiając solidne i znaczące porządki sortowania.
Jak wskazano
Shog9
, odpowiedź na twoje pytanie brzmi:Dalsza lektura:
Dzięki ładnej odpowiedzi Shog9, która wydaje mi się, że „we właściwym kierunku”
źródło
Odpowiedź (w Modern ECMAScript)
Lub
Opis
Rzutowanie wartości logicznej na liczbę daje następujące wyniki:
true
->1
false
->0
Rozważ trzy możliwe wzorce:
(x > y) - (y < x)
->1 - 0
->1
(x > y) - (y < x)
->0 - 0
->0
(x > y) - (y < x)
->0 - 1
->-1
(Alternatywny)
+(x > y) || -(x < y)
->1 || 0
->1
+(x > y) || -(x < y)
->0 || 0
->0
+(x > y) || -(x < y)
->0 || -1
->-1
Te logiki są więc równoważne typowym funkcjom komparatora sortowania.
źródło
localeCompare
i porównanie standardowe dają różne wyniki. Czego oczekujesz?["A", "b", "C", "d"].sort((a, b) => a.localeCompare(b))
sortuje w kolejności alfabetycznej bez rozróżniania wielkości liter, a["A", "b", "C", "d"].sort((a, b) => (a > b) - (a < b))
robi to w porządkuPowinieneś użyć> lub <i == tutaj. Tak więc rozwiązaniem byłoby:
źródło
Zagnieżdżona funkcja strzałki trójskładnikowej
źródło
ponieważ ciągi znaków można porównywać bezpośrednio w javascript, spełni to zadanie
odejmowanie w funkcji sortowania jest używane tylko wtedy, gdy pożądane jest sortowanie nie alfabetyczne (numeryczne) i oczywiście nie działa z łańcuchami
źródło
Martwiłem się tym przez długi czas, więc w końcu to zbadałem i podałem ci ten długi powód, dlaczego rzeczy są takie, jakie są.
Ze specyfikacji :
Teraz przechodzimy do 11.9.6
Otóż to. Potrójny operator równości zastosowany do ciągów zwraca true, jeśli argumenty są dokładnie tymi samymi ciągami (ta sama długość i te same znaki w odpowiednich pozycjach).
Tak więc
===
będzie działać w przypadkach, gdy próbujemy porównać ciągi, które mogły przybyć z różnych źródeł, ale które, jak wiemy, ostatecznie będą miały te same wartości - dość powszechny scenariusz dla wbudowanych ciągów w naszym kodzie. Na przykład, jeśli mamy zmienną o nazwieconnection_state
, i chcemy wiedzieć, który z poniższych stanów['connecting', 'connected', 'disconnecting', 'disconnected']
jest w tej chwili, możemy bezpośrednio użyć===
.Ale jest coś więcej. Tuż powyżej wersji 11.9.4 jest krótka notatka:
Hmm Co teraz? Zewnętrznie uzyskane struny mogą i najprawdopodobniej będą dziwnym jednorożcem, a nasi delikatni
===
nie oddadzą im sprawiedliwości. PrzychodzilocaleCompare
na ratunek:Możemy już iść do domu.
tl; dr;
Aby porównać ciągi w javascript, użyj
localeCompare
; jeśli wiesz, że ciągi nie zawierają żadnych elementów spoza ASCII, ponieważ są one na przykład wewnętrznymi stałymi programu, to===
również działa.źródło
W swojej operacji w początkowym pytaniu wykonujesz następującą operację:
Zakładając, że są to liczby (tj. Item1.attr = „1”, item2.attr = „2”) Nadal możesz używać operatora „===” (lub innych ścisłych ewaluatorów) pod warunkiem, że zapewnisz typ. Następujące powinny działać:
Jeśli są alphaNumeric, użyj localCompare ().
źródło
Jak działają próbki:
źródło
źródło
źródło