Как сортировать строки в JavaScript



у меня есть список объектов, которые я хочу отсортировать на основе поля attr типа string. Я пробовал использовать -



list.sort(function (a, b) {
return a.attr - b.attr
})


но обнаружил, что - не работает со строками в JavaScript. Как я могу отсортировать список объектов на основе атрибута с типом string?

1017   8  

8 ответов:

использовать String.prototype.localeCompare a в вашем примере:

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'

когда можно было бы ожидать, что специальные символы будут "сгруппированы" вместе в одном месте, за исключением специального символа пробела, возможно (который всегда будет первым символом). То есть либо все перед цифрами, либо все между цифрами и буквами (строчные и прописные буквы "вместе" друг за другом), либо все после букв.

мой вывод заключается в том, что все они не могут обеспечить последовательный порядок, когда я начинаю добавлять едва необычные символы (т. е. символы с диакритическими знаками или символами, такими как тире, восклицательный знак и так далее).

исследования на заказ реализации:

собственные реализации "естественного порядка сортировки строк" браузеров через 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 имеют другой порядок сортировки для строк.

исследование браузера-родной реализации:

сложность "строки естественного порядка сортировки"

реализация твердого алгоритма (что означает: последовательный, но также охватывающий широкий спектр символов) является очень сложной задачей. 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);

читайте далее:

спасибо к хорошему ответу 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

    Ничего не найдено.