Как сортировать строки в JavaScript
у меня есть список объектов, которые я хочу отсортировать на основе поля attr типа string. Я пробовал использовать -
list.sort(function (a, b) {
return a.attr - b.attr
})
но обнаружил, что - не работает со строками в JavaScript. Как я могу отсортировать список объектов на основе атрибута с типом string?
8 ответов:
использовать
String.prototype.localeComparea в вашем примере:list.sort(function (a, b) { return ('' + a.attr).localeCompare(b.attr); })мы заставляем a. attr быть строкой, чтобы избежать исключений.
localeCompareподдерживаются начиная с Internet Explorer 6 и Firefox 1. Вы также можете увидеть следующий код, который не учитывает языковой стандарт:if (item1.attr < item2.attr) return -1; if ( item1.attr > item2.attr) return 1; return 0;
обновленный ответ (октябрь 2014 года)
я был очень раздражен этим естественным порядком сортировки строк, поэтому мне потребовалось довольно много времени, чтобы исследовать эту проблему. Надеюсь, это поможет.
короче
localeCompare()поддержка символов-это задира, просто используйте его. Как указалShog9, ответ на ваш вопрос:return item1.attr.localeCompare(item2.attr);ошибки, найденные во всех пользовательских javascript " естественный порядок сортировки строк" реализации
есть довольно много пользовательских реализаций там, пытаясь сделать сравнение строк более точно называется "естественный порядок сортировки строк"
когда я " играл "с этими реализациями, я всегда замечал какой-то странный выбор" естественного порядка сортировки", а точнее ошибки (или упущения в лучших случаях).
как правило, специальные символы (пробел, тире, амперсанд, скобки и т. д.) не обрабатываются правильно.
затем вы обнаружите, что они появляются в разных местах, как правило, это может быть:
- некоторые будут между прописными буквами " Z "и строчными буквами "a"
- какой будет между '9' и прописные "а"
- некоторые будут после строчной буквы 'Z'
когда можно было бы ожидать, что специальные символы будут "сгруппированы" вместе в одном месте, за исключением специального символа пробела, возможно (который всегда будет первым символом). То есть либо все перед цифрами, либо все между цифрами и буквами (строчные и прописные буквы "вместе" друг за другом), либо все после букв.
мой вывод заключается в том, что все они не могут обеспечить последовательный порядок, когда я начинаю добавлять едва необычные символы (т. е. символы с диакритическими знаками или символами, такими как тире, восклицательный знак и так далее).
исследования на заказ реализации:
Natural Compare Litehttps://github.com/litejs/natural-compare-lite: не удается последовательно сортировать https://github.com/litejs/natural-compare-lite/issues/1 и http://jsbin.com/bevututodavi/1/edit?js, консоль, сортировка основных латинских символовhttp://jsbin.com/bevututodavi/5/edit?js, консольNatural Sorthttps://github.com/javve/natural-sort : не сортировка последовательно, см. выпуск https://github.com/javve/natural-sort/issues/7 и смотрите основные латинские символы сортировки http://jsbin.com/cipimosedoqe/3/edit?js, консольJavascript Natural Sorthttps://github.com/overset/javascript-natural-sort: кажется, довольно пренебрегают с февраля 2012 года, не удается последовательно сортировать, см. выпуск https://github.com/overset/javascript-natural-sort/issues/16Alphanumhttp://www.davekoelle.com/files/alphanum.js, не удается последовательно сортировать, см. http://jsbin.com/tuminoxifuyo/1/edit?js, консольсобственные реализации "естественного порядка сортировки строк" браузеров через
localeCompare()
localeCompare()самая старая реализация (без аргументов locales и options) поддерживается IE6+, см. http://msdn.microsoft.com/en-us/library/ie/s4esdbwz (v=vs.94). aspx (прокрутите вниз до метод localeCompare (). ВстроенныйlocaleCompare()способ делает намного лучшую работу по сортировке, даже международные и специальные символы. Единственная проблема с использованиемlocaleCompare()метод заключается в том, что "используемая локаль и порядок сортировки полностью зависят от реализации". Другими словами, при использовании localeCompare, таких как stringOne.localeCompare (stringTwo): Firefox, Safari, Chrome & IE имеют другой порядок сортировки для строк.исследование браузера-родной реализации:
- http://jsbin.com/beboroyifomu/1/edit?js, console - сравнение основных латинских символов с localeCompare() http://jsbin.com/viyucavudela/2/ - сравнение основных латинских символов с localeCompare () для тестирования на IE8
- http://jsbin.com/beboroyifomu/2/edit?js, console - основные латинские символы в сравнении строк: проверка согласованности в строке vs, когда символ один
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/localeCompare- IE11 + поддерживает новые аргументы locales & options
сложность "строки естественного порядка сортировки"
реализация твердого алгоритма (что означает: последовательный, но также охватывающий широкий спектр символов) является очень сложной задачей. UTF8 содержит более 2000 символов & покрывает больше чем 120 скрипты (языках). Наконец, есть некоторые спецификации для этой задачи, она называется "алгоритм сортировки Unicode", который можно найти в http://www.unicode.org/reports/tr10/ . Вы можете найти дополнительную информацию об этом по этому вопросу, который я опубликовал https://softwareengineering.stackexchange.com/questions/257286/is-there-any-language-agnostic-specification-for-string-natural-sorting-order
финал вывод
поэтому, учитывая текущий уровень поддержки, обеспечиваемый пользовательскими реализациями javascript, с которыми я столкнулся, мы, вероятно, никогда не увидим, что что-то приближается к поддержке всех этих символов и скриптов (языков). Поэтому я бы предпочел использовать собственный метод localecompare () браузеров. Да, у него есть обратная сторона несогласованности между браузерами, но базовое тестирование показывает, что он охватывает гораздо более широкий диапазон символов, позволяя сплошную и значимую сортировку заказы.
так как указано
Shog9, ответ на ваш вопрос:return item1.attr.localeCompare(item2.attr);читайте далее:
- https://softwareengineering.stackexchange.com/questions/257286/is-there-any-language-agnostic-specification-for-string-natural-sorting-order
- как вы делаете сравнение строк в JavaScript?
- Javascript: естественный вид буквенно-цифровой строки
- сортировка массива числовых и алфавитных элементов (естественная сортировка)
- сортировка смешанных буквенно-цифрового массив
- https://web.archive.org/web/20130929122019/http://my.opera.com/GreyWyvern/blog/show.dml/1671288
- https://web.archive.org/web/20131005224909/http://www.davekoelle.com/alphanum.html
- http://snipplr.com/view/36012/javascript-natural-sort/
- http://blog.codinghorror.com/sorting-for-humans-natural-sort-order/
спасибо к хорошему ответу Shog9, который поставил меня в" правильном " направлении, я считаю
самый простой ответ с ECMAScript 2016
list.sort((a, b) => (a.attr > b.attr) - (a.attr < b.attr))или
list.sort((a, b) => +(a.attr > b.attr) || -(a.attr < b.attr))
вы должны использовать > или
list.sort(function(item1, item2) { var val1 = item1.attr, val2 = item2.attr; if (val1 == val2) return 0; if (val1 > val2) return 1; if (val1 < val2) return -1; });
я долго беспокоился об этом, поэтому я, наконец, исследовал это и дал вам эту длинную причину, почему все так, как есть.
С spec:
Section 11.9.4 The Strict Equals Operator ( === ) The production EqualityExpression : EqualityExpression === RelationalExpression is evaluated as follows: - Let lref be the result of evaluating EqualityExpression. - Let lval be GetValue(lref). - Let rref be the result of evaluating RelationalExpression. - Let rval be GetValue(rref). - Return the result of performing the strict equality comparison rval === lval. (See 11.9.6)Итак, теперь мы переходим к 11.9.6
11.9.6 The Strict Equality Comparison Algorithm The comparison x === y, where x and y are values, produces true or false. Such a comparison is performed as follows: - If Type(x) is different from Type(y), return false. - If Type(x) is Undefined, return true. - If Type(x) is Null, return true. - If Type(x) is Number, then ... - If Type(x) is String, then return true if x and y are exactly the same sequence of characters (same length and same characters in corresponding positions); otherwise, return false.вот и все. оператор triple equals, применяемый к строкам, возвращает true, если аргументы являются точно такими же строками (одинаковая длина и одинаковые символы в соответствующих должностное положение.)
так
===будет работать в тех случаях, когда мы пытаемся сравнить строки, которые могли бы поступить из разных источников, но которые, как мы знаем, в конечном итоге будут иметь одинаковые значения - достаточно распространенный сценарий для встроенных строк в нашем коде. Например, если у нас есть переменная с именемconnection_state, и мы хотим знать, какое из следующих состояний['connecting', 'connected', 'disconnecting', 'disconnected']это сейчас, мы можем напрямую использовать===.но это еще не все. Прямо над 11.9.4, есть короткое Примечание:
NOTE 4 Comparison of Strings uses a simple equality test on sequences of code unit values. There is no attempt to use the more complex, semantically oriented definitions of character or string equality and collating order defined in the Unicode specification. Therefore Strings values that are canonically equal according to the Unicode standard could test as unequal. In effect this algorithm assumes that both Strings are already in normalized form.Мда. И что теперь? Внешне полученные струны могут, и скорее всего будут, быть странными unicodey, а наши нежные
===не будет воздавать им должное. ВходитlocaleCompareна помощь:15.5.4.9 String.prototype.localeCompare (that) ... The actual return values are implementation-defined to permit implementers to encode additional information in the value, but the function is required to define a total ordering on all Strings and to return 0 when comparing Strings that are considered canonically equivalent by the Unicode standard.теперь мы можем идти домой.
tl; dr;
чтобы сравнить строки в javascript, используйте
localeCompare; если вы знаете, что строки не имеют компонентов, отличных от ASCII, потому что они, например, являются внутренней программой значит, константы===тоже работает.
<!doctype html> <html> <body> <p id = "myString">zyxtspqnmdba</p> <p id = "orderedString"></p> <script> var myString = document.getElementById("myString").innerHTML; orderString(myString); function orderString(str) { var i = 0; var myArray = str.split(""); while (i < str.length){ var j = i + 1; while (j < str.length) { if (myArray[j] < myArray[i]){ var temp = myArray[i]; myArray[i] = myArray[j]; myArray[j] = temp; } j++; } i++; } var newString = myArray.join(""); document.getElementById("orderedString").innerHTML = newString; } </script> </body> </html>
в вашей операции в вашем первоначальном вопросе вы выполняете следующую операцию:
item1.attr - item2.attrИтак, предполагая, что это числа (т. е. item1.attr = "1", item2.attr = "2") вы все еще можете использовать оператор "= = = " (или другие строгие оценщики) при условии, что вы гарантируете тип. Должно работать следующее:
return parseInt(item1.attr) - parseInt(item2.attr);если они буквенно-цифровые, то используйте localCompare().
list.sort(function(item1, item2){ return +(item1.attr > item2.attr) || +(item1.attr === item2.attr) - 1; })как они работают образцы:
+('aaa'>'bbb')||+('aaa'==='bbb')-1 +(false)||+(false)-1 0||0-1 -1 +('bbb'>'aaa')||+('bbb'==='aaa')-1 +(true)||+(false)-1 1||0-1 1 +('aaa'>'aaa')||+('aaa'==='aaa')-1 +(false)||+(true)-1 0||1-1 0
Comments