Eu tenho uma variedade de strings que preciso classificar em JavaScript, mas de uma maneira que não diferencia maiúsculas de minúsculas. Como fazer isso?
javascript
sorting
case-insensitive
Jérôme Verstrynge
fonte
fonte
return a.localeCompare(b, 'en', {'sensitivity': 'base'});
toLowerCase()
quandolocaleCompare
já o faz por padrão em alguns casos. Você pode ler mais sobre os parâmetros a serem transmitidos aqui: developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/…items.sort(new Intl.Collator('en').compare)
para obter melhor desempenho. (Veja MDN .)Edição: Por favor, note que eu escrevi isso originalmente para ilustrar a técnica, em vez de ter o desempenho em mente. Consulte também a resposta a @Ivan Krechetov para obter uma solução mais compacta.
fonte
toLowerCase
duas vezes em cada string; seria mais eficiente armazenar versões reduzidas da string em variáveis..toLowerCase()
várias vezes para cada item da matriz. Por exemplo, 45 chama a função comparar ao classificar 10 itens na ordem inversa.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("Calls to Compare: " + i); // i === 45
É hora de revisitar essa velha questão.
Você não deve usar soluções confiáveis
toLowerCase
. Eles são ineficientes e simplesmente não funcionam em alguns idiomas (turco, por exemplo). Prefira isto:Verifique a documentação quanto à compatibilidade do navegador e tudo o que há para saber sobre a
sensitivity
opção.fonte
fonte
return a === b ? 0 : a > b ? 1 : -1;
["111", "33"]
, podemos querer que retorne["111", "33"]
porque 1 vem antes de 3 na ordenação do código de caracteres. No entanto, a função nesta resposta retornará["33", "111"]
porque o número33
é menor que o número111
."33" > "111" === true
e33 > 111 === false
. Funciona como pretendido.Você também pode usar o novo
Intl.Collator().compare
, por MDN, é mais eficiente na classificação de matrizes. A desvantagem é que não é suportado por navegadores mais antigos. O MDN afirma que não é suportado no Safari. Precisa verificar, pois afirma queIntl.Collator
é suportado.fonte
Se você deseja garantir a mesma ordem, independentemente da ordem dos elementos na matriz de entrada, aqui está uma classificação estável :
fonte
Normalize o caso
.sort()
com.toLowerCase()
.fonte
Você também pode usar o operador Elvis:
Dá:
O método localeCompare provavelmente é bom ...
Nota: O operador Elvis é uma forma abreviada de 'operador ternário', caso contrário, geralmente com atribuição.
Se você olhar para?: De lado, parece Elvis ...
ou seja, em vez de:
você pode usar:
ou seja, quando y for verdadeiro, retorne 1 (para a atribuição a x), caso contrário, retorne 2 (para a atribuição a x).
fonte
x = y ? y : z
, você pode fazerx = y ?: z
. O Javascript não possui um operador Elvis real, mas você pode usá-lo dex = y || z
maneira semelhante.As outras respostas assumem que a matriz contém seqüências de caracteres. Meu método é melhor, porque funcionará mesmo que a matriz contenha nulas, indefinidas ou outras não-seqüências de caracteres.
O
null
será classificado entre 'nulk' e 'nulm'. Mas oundefined
será sempre classificado por último.fonte
(''+notdefined) === "undefined"
por isso gostaria classificar antes de "z"Array.prototype.sort
: | porque a parte sobre(''+notdefined) === "undefined"
realmente é verdadeira ... o que significa que se você girar o -1 e 1 na função de classificação para reverter a ordem, indefinido ainda será classificado até o fim. Também precisa ser considerado ao usar a função de comparação fora do contexto de uma classificação de matriz (como eu era quando me deparei com essa pergunta).Array.prototype.sort
definição - faça mais alguns comentários. Primeiro, não há necessidade de o(''+a)
- ECMAScript precisartoString()
ser chamado nos elementos antes de passá-los para compareFn. Segundo, o fato deignoreCase
retornar1
ao comparar seqüências de caracteres iguais (incluindo iguais mas para o caso) significa que a especificação não define o resultado se houver valores duplicados (provavelmente será bom apenas com algumas trocas desnecessárias, eu acho).undefined
é um caso especial, que para qualquer x x <indefinido ex > indefinido são ambos falsos . Issoundefined
é sempre o último, é um subproduto da implementação de classificação de classificação. Tentei mudar o ('' + a) para simplesmente a, mas ele falhou. eu entendoTypeError: a.toUpperCase is not a function
. Aparentemente, nãotoString
é chamado antes de chamar compareFn.undefined
o compareFn nuncaVersão ES6:
["Foo", "bar"].sort((a, b) => a.localeCompare(b, 'en', { sensitivity: 'base' }))
Fonte: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/localeCompare
fonte
Em apoio à resposta aceita, gostaria de acrescentar que a função abaixo parece alterar os valores na matriz original a serem classificados, para que não apenas classifique em minúsculas, mas também em maiúsculas. Isso é um problema para mim, porque, embora eu deseje ver Mary próxima a Mary, não desejo que o caso do primeiro valor Mary seja alterado para minúsculo.
Nas minhas experiências, a seguinte função da resposta aceita é classificada corretamente, mas não altera os valores.
fonte
Isso pode ajudar se você tiver se esforçado para entender:
http://jsfiddle.net/ianjamieson/wmxn2ram/1/
fonte
Na função acima, se apenas compararmos quando as minúsculas dois valor a e b, não teremos o resultado bonito.
Exemplo, se a matriz é [A, a, B, b, c, C, D, d, e, E] e usamos a função acima, temos exatamente essa matriz. Não mudou nada.
Para que o resultado seja [A, a, B, b, C, c, D, d, E, e], devemos comparar novamente quando dois valores em minúsculas forem iguais:
fonte
Embrulhei a resposta principal em um polyfill para poder chamar .sortIgnoreCase () em matrizes de string
fonte
Enrole suas cordas
/ /i
. Essa é uma maneira fácil de usar o regex para ignorar a caixafonte