Как выполнить сортировку без учета регистра в JavaScript? - PullRequest
183 голосов
/ 25 января 2012

У меня есть массив строк, которые мне нужно отсортировать в JavaScript, но без учета регистра. Как это сделать?

Ответы [ 13 ]

342 голосов
/ 10 марта 2012

В (почти :) однострочник

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

Что приводит к

[ 'bar', 'Foo' ]

Пока

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

Результаты в

[ 'Foo', 'bar' ]
58 голосов
/ 25 января 2012
myArray.sort(
  function(a, b) {
    if (a.toLowerCase() < b.toLowerCase()) return -1;
    if (a.toLowerCase() > b.toLowerCase()) return 1;
    return 0;
  }
);

РЕДАКТИРОВАТЬ: Обратите внимание, что я изначально написал это, чтобы проиллюстрировать технику, а не иметь в виду производительность.Пожалуйста, обратитесь к ответу @Ivan Krechetov для более компактного решения.

26 голосов
/ 27 февраля 2018

Настало время вернуться к этому старому вопросу.

Вы не должны использовать решения, основанные на toLowerCase.Они неэффективны и просто не работают на некоторых языках (например, на турецком).Предпочитайте следующее:

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

Проверьте документацию на совместимость с браузером и все, что нужно знать о опции sensitivity.

24 голосов
/ 25 января 2012
arr.sort(function(a,b) {
    a = a.toLowerCase();
    b = b.toLowerCase();
    if (a == b) return 0;
    if (a > b) return 1;
    return -1;
});
10 голосов
/ 26 сентября 2014

Если вы хотите гарантировать один и тот же порядок независимо от порядка элементов во входном массиве, вот сортировка stable :

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;
});
8 голосов
/ 03 ноября 2016

Вы также можете использовать новые Intl.Collator().compare, за MDN это более эффективно при сортировке массивов. Недостатком является то, что он не поддерживается старыми браузерами. MDN заявляет, что он вообще не поддерживается в Safari. Нужно проверить это, поскольку в нем говорится, что Intl.Collator поддерживается.

При сравнении большого количества строк, например при сортировке больших массивов, лучше создать объект Intl.Collator и использовать функцию, предоставляемую его свойством сравнения

["Foo", "bar"].sort(Intl.Collator().compare); //["bar", "Foo"]
4 голосов
/ 25 января 2012

Нормализовать регистр в .sort() с помощью .toLowerCase().

3 голосов
/ 09 сентября 2016

Другие ответы предполагают, что массив содержит строки. Мой метод лучше, потому что он будет работать, даже если массив содержит null, undefined или другие нестандартные строки.

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;
}

null будет отсортировано между 'nulk' и 'nulm'. Но undefined будет всегда отсортированным последним.

2 голосов
/ 01 октября 2014

Вы также можете использовать оператор Элвиса:

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);

Дает:

biscuit,Bob,charley,fudge,Fudge

Метод localeCompare, вероятно, хорошо, хотя ...

Примечание. Оператор Элвиса - это краткая форма «троичного оператора» для, если не в другом месте, обычно с присваиванием.
Если вы посмотрите на?: Sideway, он будет выглядеть как Элвис ...
, то есть вместо:

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

вы можете использовать:

x = y?1:2;

то есть, когда y истинно, затем вернуть 1 (для присвоения x), в противном случае вернуть 2 (для присвоения x).

0 голосов
/ 31 марта 2017

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

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