2012-01-25 4 views

ответ

265

В (почти :) один вкладыш

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

Какие результаты в

[ 'bar', 'Foo' ] 

В то время как

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

приводит

[ 'Foo', 'bar' ] 
+7

Помните, что расширенные параметры localeCompare еще не поддерживаются на всех платформах/браузерах. Я знаю, что они не используются в этом примере, а просто хотят добавить для ясности. [См. MDN для получения дополнительной информации] (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/localeCompare) –

+50

Если вы собираетесь задействовать localeCompare(), вы можете просто используйте * его * способность быть нечувствительным к регистру, например: 'return a.localeCompare (b, 'en', {'sensitive': 'base'});' –

+1

+1 для того, чтобы не вызывать 'toLowerCase()' когда 'localeCompare' уже делает это по умолчанию в некоторых случаях. Подробнее о параметрах, которые можно передать здесь, можно здесь: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/localeCompare#Parameters – Milimetric

4

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

21
arr.sort(function(a,b) { 
    a = a.toLowerCase(); 
    b = b.toLowerCase(); 
    if (a == b) return 0; 
    if (a > b) return 1; 
    return -1; 
}); 
+0

или 'return a === b? 0: a> b? 1: -1; ' –

55
myArray.sort(
    function(a, b) { 
    if (a.toLowerCase() < b.toLowerCase()) return -1; 
    if (a.toLowerCase() > b.toLowerCase()) return 1; 
    return 0; 
    } 
); 

EDIT: Пожалуйста, обратите внимание, что я первоначально написал это, чтобы проиллюстрировать технику, а не имеющие производительность в виду. Также см. Ответ @ Ивана Кречетова для более компактного решения.

+3

Это может вызывать' toLowerCase' дважды для каждой строки; было бы более эффективно хранить пониженные версии строки в переменных. – Jacob

+0

Правда и спасибо. Я написал это с ясностью в виду, а не с производительностью. Наверное, я должен это отметить. –

+1

@ Jacob. Чтобы быть справедливым, принятый ответ имеет одну и ту же основную проблему: он может несколько раз вызывать '.toLowerCase()' для каждого элемента массива. Например, 45 вызовов функции сравнения при сортировке 10 элементов в обратном порядке. '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 («Вызовы для сравнения:» + i); // i === 45' – nothingisnecessary

8

Если вы хотите, чтобы гарантировать тот же порядок, независимо от порядка элементов во входном массиве, вот 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; 
}); 
3

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

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, вероятно, хорошо, хотя ...

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

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

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

x = y?1:2; 

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

0

Это может помочь, если вы изо всех сил, чтобы понять:

var array = ["sort", "Me", "alphabetically", "But", "Ignore", "case"]; 
console.log('Unordered array ---', array, '------------'); 

array.sort(function(a,b) { 
    a = a.toLowerCase(); 
    b = b.toLowerCase(); 
    console.log("Compare '" + a + "' and '" + b + "'"); 

    if(a == b) { 
     console.log('Comparison result, 0 --- leave as is '); 
     return 0; 
    } 
    if(a > b) { 
     console.log('Comparison result, 1 --- move '+b+' to before '+a+' '); 
     return 1; 
    } 
    console.log('Comparison result, -1 --- move '+a+' to before '+b+' '); 
    return -1; 


}); 

console.log('Ordered array ---', array, '------------'); 


// return logic 

/*** 
If compareFunction(a, b) is less than 0, sort a to a lower index than b, i.e. a comes first. 
If compareFunction(a, b) returns 0, leave a and b unchanged with respect to each other, but sorted with respect to all different elements. Note: the ECMAscript standard does not guarantee this behaviour, and thus not all browsers (e.g. Mozilla versions dating back to at least 2003) respect this. 
If compareFunction(a, b) is greater than 0, sort b to a lower index than a. 
***/ 

http://jsfiddle.net/ianjamieson/wmxn2ram/1/

0
arr.sort(function(a,b) { 
    a = a.toLowerCase(); 
    b = b.toLowerCase(); 
    if(a == b) return 0; 
    if(a > b) return 1; 
    return -1; 
}); 

В приведенной выше функции, если мы сравниваем, когда нижний регистр два значения а и Ь, мы не будем иметь красивый результат.

Пример: если массив является [A, a, B, b, c, C, D, d, e, E] и мы используем указанную выше функцию, мы имеем именно этот массив. Ничего не изменилось.

Для того, чтобы получить результат в [А, а, B, B, C, C, D, D, Е, е], мы должны сравнить еще раз, когда два более низкое значение случае равно:

function caseInsensitiveComparator(valueA, valueB) { 
    var valueALowerCase = valueA.toLowerCase(); 
    var valueBLowerCase = valueB.toLowerCase(); 

    if (valueALowerCase < valueBLowerCase) { 
     return -1; 
    } else if (valueALowerCase > valueBLowerCase) { 
     return 1; 
    } else { //valueALowerCase === valueBLowerCase 
     if (valueA < valueB) { 
      return -1; 
     } else if (valueA > valueB) { 
      return 1; 
     } else { 
      return 0; 
     } 
    } 
} 
0

Оберните свои струны в / /i. Это простой способ использовать регулярное выражение для игнорирования обсадной колонны.

1

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

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

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

+0

'('' + notdefined) ===" undefined "' поэтому он сортирует до "z" – MattW

+0

@MattW, если вы ошибаетесь. см. https://jsfiddle.net/qrw0uy3r/ –

+0

Угадай, что я должен был найти определение 'Array.prototype.sort': | потому что часть о '('' + notdefined) ===" undefined "' * действительно is * true ... что означает, что если вы переверните -1 и 1 в функции сортировки, чтобы отменить порядок, undefined все еще сортирует конец. Это также необходимо учитывать при использовании функции сравнения вне контекста сортировки массива (как и было, когда я столкнулся с этим вопросом). – MattW

3

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

When comparing large numbers of strings, such as in sorting large arrays, it is better to create an Intl.Collator object and use the function provided by its compare property

["Foo", "bar"].sort(Intl.Collator().compare); //["bar", "Foo"] 
+0

Винт старых браузеров; Я использую это. –

0

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

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

Пора пересмотреть этот старый вопрос.

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

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

Проверьте documentation для совместимости браузера и все, что нужно знать о возможности sensitivity.

Смежные вопросы