Eu tenho uma lista de objetos que desejo classificar com base em um campo attr
do tipo string. Eu tentei usar-
list.sort(function (a, b) {
return a.attr - b.attr
})
mas descobriu que -
não parece funcionar com cadeias de caracteres em JavaScript. Como posso classificar uma lista de objetos com base em um atributo com o tipo string?
javascript
string
airportyh
fonte
fonte
JavaScript case insensitive string comparison
em stackoverflow.com/questions/2140627/…Javascript : remove accents/diacritics in strings
em stackoverflow.com/questions/990904/…Respostas:
Use
String.prototype.localeCompare
um por seu exemplo:Forçamos a.attr a ser uma string para evitar exceções.
localeCompare
é suportado desde o Internet Explorer 6 e Firefox 1. Você também pode ver o seguinte código usado que não respeita um código de idioma:fonte
localeCompare()
não se depara com esse problema, mas não entende os valores numéricos, então você obterá ["1", "10", "2"] como nas comparações de classificação na maioria dos idiomas. se você quiser classificar para sua extremidade dianteira UI, olhar para o alphanum / classificação natural algoritmo stackoverflow.com/questions/4340227/... ou stackoverflow.com/questions/4321829/...localeCompare()
é suportado apenas em navegadores modernos: IE11 + no momento da redação deste artigo, consulte developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…localeCompare()
várias versões anteriores, mas não especifica a localidade até a versão 11. Observe também as perguntas às quais o Dead.Rabit se vinculou.Uma resposta atualizada (outubro de 2014)
Fiquei realmente irritado com essa ordem de classificação natural da string, por isso levei algum tempo para investigar esse problema. Eu espero que isso ajude.
Longa história curta
localeCompare()
suporte a personagens é foda, basta usá-lo. Conforme indicado porShog9
, a resposta para sua pergunta é:Erros encontrados em todas as implementações personalizadas de "ordem de classificação de sequência natural" em javascript
Existem várias implementações personalizadas por aí, tentando fazer uma comparação de strings mais precisamente chamada "ordem natural de classificação de strings"
Ao "brincar" com essas implementações, sempre notei alguma escolha estranha de "ordem de classificação natural", ou melhor, erros (ou omissões nos melhores casos).
Normalmente, caracteres especiais (espaço, traço, e comercial, colchetes e assim por diante) não são processados corretamente.
Você os encontrará aparecendo misturados em lugares diferentes, normalmente que podem ser:
Quando seria de esperar que todos os caracteres especiais fossem "agrupados" em um só lugar, exceto o caractere especial de espaço talvez (que sempre seria o primeiro caractere). Ou seja, tudo antes dos números ou entre números e letras (letras minúsculas e maiúsculas estão "juntas" uma após a outra) ou todas as letras.
Minha conclusão é que todos eles falham em fornecer uma ordem consistente quando começo a adicionar caracteres pouco comuns (ou seja, caracteres com sinais diacríticos ou caracteres como traço, ponto de exclamação e assim por diante).
Pesquisa sobre implementações personalizadas:
Natural Compare Lite
https://github.com/litejs/natural-compare-lite : falha na classificação consistente https://github.com/litejs/natural-compare-lite/issues/1 e http://jsbin.com/bevututodavi/ 1 / edit? Js, console , classificação básica de caracteres latinos http://jsbin.com/bevututodavi/5/edit?js,consoleNatural Sort
https://github.com/javve/natural-sort : falha na classificação consistente, consulte o problema https://github.com/javve/natural-sort/issues/7 e veja os caracteres latinos básicos da classificação http: // jsbin. com / cipimosedoqe / 3 / edit? js, consoleJavascript Natural Sort
https://github.com/overset/javascript-natural-sort : parece bastante negligenciado desde fevereiro de 2012, falha na classificação consistente, consulte o problema https://github.com/overset/javascript-natural-sort/issues/16Alphanum
http://www.davekoelle.com/files/alphanum.js , falha na classificação consistente, consulte http://jsbin.com/tuminoxifuyo/1/edit?js,consoleImplementações nativas da "ordem de classificação de cadeia natural" dos navegadores via
localeCompare()
localeCompare()
A implementação mais antiga (sem os argumentos códigos de idioma e opções) é suportada pelo IE6 +, consulte http://msdn.microsoft.com/en-us/library/ie/s4esdbwz(v=vs.94).aspx (role para baixo até localeCompare ( )). OlocaleCompare()
método incorporado faz um trabalho muito melhor na classificação, mesmo em caracteres internacionais e especiais. O único problema usando olocaleCompare()
método é que "a localidade e a ordem de classificação usadas são totalmente dependentes da implementação". Em outras palavras, ao usar o localeCompare, como stringOne.localeCompare (stringTwo): Firefox, Safari, Chrome e IE têm uma ordem de classificação diferente para Strings.Pesquisa sobre implementações nativas do navegador:
Dificuldade de "ordem de classificação natural das cadeias"
A implementação de um algoritmo sólido (significando: consistente, mas também cobrindo uma ampla variedade de caracteres) é uma tarefa muito difícil. O UTF8 contém mais de 2000 caracteres e abrange mais de 120 scripts (idiomas) . Finalmente, existem algumas especificações para essas tarefas, chamadas de "Algoritmos de Collation Unicode", que podem ser encontrados em http://www.unicode.org/reports/tr10/ . Você pode encontrar mais informações sobre isso nesta questão que eu publiquei /software/257286/is-there-any-language-agnostic-specification-for-string-natural-sorting-order
Conclusão final
Portanto, considerando o nível atual de suporte fornecido pelas implementações personalizadas de javascript que encontrei, provavelmente nunca veremos nada próximo de suportar todos esses caracteres e scripts (idiomas). Por isso, prefiro usar o método localeCompare () nativo dos navegadores. Sim, ele tem a desvantagem de não ser consistente entre os navegadores, mas os testes básicos mostram que ele abrange uma variedade muito maior de caracteres, permitindo ordens de classificação sólidas e significativas.
Portanto, conforme indicado por
Shog9
, a resposta para sua pergunta é:Leitura adicional:
Graças à boa resposta de Shog9, que me colocou na direção "certa", acredito
fonte
Resposta (no ECMAScript moderno)
Ou
Descrição
A conversão de um valor booleano em um número produz o seguinte:
true
->1
false
->0
Considere três padrões possíveis:
(x > y) - (y < x)
->1 - 0
->1
(x > y) - (y < x)
->0 - 0
->0
(x > y) - (y < x)
->0 - 1
->-1
(Alternativa)
+(x > y) || -(x < y)
->1 || 0
->1
+(x > y) || -(x < y)
->0 || 0
->0
+(x > y) || -(x < y)
->0 || -1
->-1
Portanto, essas lógicas são equivalentes às funções típicas do comparador de classificação.
fonte
localeCompare
e a comparação padrão produzem resultados diferentes. Qual você espera?["A", "b", "C", "d"].sort((a, b) => a.localeCompare(b))
classifica em ordem alfabética case-insensitive, enquanto["A", "b", "C", "d"].sort((a, b) => (a > b) - (a < b))
faz a fim codepointVocê deve usar> ou <e == aqui. Portanto, a solução seria:
fonte
Função de seta ternária aninhada
fonte
como as strings podem ser comparadas diretamente em javascript, isso fará o trabalho
a subtração em uma função de classificação é usada apenas quando a classificação não alfabética (numérica) é desejada e, é claro, não funciona com strings
fonte
Eu me preocupei com isso por muito tempo, então finalmente pesquisei sobre isso e explico por que as coisas são do jeito que são.
Das especificações :
Então agora vamos para 11.9.6
É isso aí. O operador triple equals aplicado às strings retorna true se os argumentos são exatamente as mesmas strings (mesmo comprimento e mesmos caracteres nas posições correspondentes).
Portanto
===
, funcionará nos casos em que estivermos tentando comparar cadeias que podem ter chegado de fontes diferentes, mas que sabemos que acabarão tendo os mesmos valores - um cenário bastante comum para cadeias de caracteres embutidas em nosso código. Por exemplo, se tivermos uma variável denominadaconnection_state
e desejamos saber em qual dos seguintes estados['connecting', 'connected', 'disconnecting', 'disconnected']
ela está agora, podemos usar diretamente o===
.Mas tem mais. Logo acima do 11.9.4, há uma breve nota:
Hmm. E agora? Cordas obtidas externamente podem, e muito provavelmente serão, unicodey estranho, e nosso gentil
===
não fará justiça a elas. Em vemlocaleCompare
ao salvamento:Podemos ir para casa agora.
tl; dr;
Para comparar strings em javascript, use
localeCompare
; se você souber que as seqüências não têm componentes não ASCII porque são, por exemplo, constantes internas do programa,===
também funciona.fonte
Na sua operação na sua pergunta inicial, você está executando a seguinte operação:
Portanto, supondo que sejam números (por exemplo, item1.attr = "1", item2.attr = "2") Você ainda pode usar o operador "===" (ou outros avaliadores rigorosos), desde que garanta o tipo. O seguinte deve funcionar:
Se eles são alphaNumeric, use localCompare ().
fonte
Como eles funcionam amostras:
fonte
fonte
fonte