Tengo una serie de cadenas que necesito ordenar en JavaScript, pero sin distinción entre mayúsculas y minúsculas. ¿Cómo realizar esto?
javascript
sorting
case-insensitive
Jérôme Verstrynge
fuente
fuente
return a.localeCompare(b, 'en', {'sensitivity': 'base'});
toLowerCase()
cuandolocaleCompare
ya lo hace de forma predeterminada en algunos casos. Puede leer más sobre los parámetros para pasar aquí: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…items.sort(new Intl.Collator('en').compare)
para un mejor rendimiento. (Ver MDN .)EDITAR: Tenga en cuenta que originalmente escribí esto para ilustrar la técnica en lugar de tener en cuenta el rendimiento. Consulte también la respuesta @Ivan Krechetov para obtener una solución más compacta.
fuente
toLowerCase
dos veces en cada cadena; Sería más eficiente almacenar versiones reducidas de la cadena en variables..toLowerCase()
varias veces para cada elemento del conjunto. Por ejemplo, 45 llamadas a la función de comparación al ordenar 10 elementos en orden inverso.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
Es hora de revisar esta vieja pregunta.
No debe usar soluciones confiables
toLowerCase
. Son ineficientes y simplemente no funcionan en algunos idiomas (turco, por ejemplo). Prefiero esto:Consulte la documentación de compatibilidad del navegador y todo lo que hay que saber sobre la
sensitivity
opción.fuente
fuente
return a === b ? 0 : a > b ? 1 : -1;
["111", "33"]
, podríamos querer que vuelva["111", "33"]
porque 1 viene antes que 3 en el orden del código de caracteres. Sin embargo, la función en esta respuesta volverá["33", "111"]
porque el número33
es menor que el número111
."33" > "111" === true
y33 > 111 === false
. Funciona según lo previsto.También puede usar el nuevo
Intl.Collator().compare
, según MDN, es más eficiente al ordenar matrices. La desventaja es que no es compatible con navegadores antiguos. MDN afirma que no es compatible en absoluto en Safari. Es necesario verificarlo, ya que indica queIntl.Collator
es compatible.fuente
Si desea garantizar el mismo orden independientemente del orden de los elementos en la matriz de entrada, aquí hay una clasificación estable :
fuente
Normalizar el caso en el
.sort()
con.toLowerCase()
.fuente
También puede usar el operador de Elvis:
Da:
Sin embargo, el método localeCompare probablemente esté bien ...
Nota: El operador de Elvis es una forma abreviada de 'operador ternario' para si, de lo contrario, generalmente con asignación.
Si miras el?: De lado, se parece a Elvis ...
es decir, en lugar de:
puedes usar:
es decir, cuando y es verdadero, luego devuelve 1 (para la asignación a x), de lo contrario devuelve 2 (para la asignación a x).
fuente
x = y ? y : z
, puede hacerlox = y ?: z
. Javascript no tiene un operador real de Elvis, pero puede usarlox = y || z
de manera similar.Las otras respuestas suponen que la matriz contiene cadenas. Mi método es mejor, porque funcionará incluso si la matriz contiene nulos, indefinidos u otras cadenas.
El
null
se ordenará entre 'nulk' y 'nulm'. Sin embargo, elundefined
será siempre ordenados pasado.fuente
(''+notdefined) === "undefined"
así que seArray.prototype.sort
: | porque la parte acerca de(''+notdefined) === "undefined"
realmente es verdadera ... lo que significa que si volteas el -1 y el 1 en la función de clasificación para revertir el orden, undefined aún se ordena hasta el final. También debe tenerse en cuenta al usar la función de comparación fuera del contexto de una ordenación de matriz (como lo hice cuando me encontré con esta pregunta).Array.prototype.sort
definición, un par de comentarios más. Primero, no hay necesidad de(''+a)
- ECMAScript requieretoString()
que se llame a elementos antes de pasarlos a compareFn. En segundo lugar, el hecho de queignoreCase
regrese1
al comparar cadenas iguales (incluidas las cadenas iguales pero para el caso) significa que la especificación no define el resultado si hay valores duplicados (creo que probablemente estará bien solo con algunos intercambios innecesarios, creo).undefined
es un caso especial, que para cualquier x x <undefined y x> undefined son falsos . Esoundefined
siempre es el último, es un subproducto de la implementación del tipo de clasificación. Intenté cambiar el ('' + a) a simplemente a, pero falla. me saleTypeError: a.toUpperCase is not a function
. Al parecertoString
se no llama antes de llamar compareFn.undefined
el compareFn nunca se llamaVersión ES6:
["Foo", "bar"].sort((a, b) => a.localeCompare(b, 'en', { sensitivity: 'base' }))
Fuente: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/localeCompare
fuente
En apoyo de la respuesta aceptada, me gustaría agregar que la función a continuación parece cambiar los valores en la matriz original que se ordenará, de modo que no solo clasificará en minúsculas sino que los valores en mayúsculas también se cambiarán a minúsculas. Esto es un problema para mí porque, aunque deseo ver a Mary junto a Mary, no deseo que el caso del primer valor Mary se cambie a minúsculas.
En mis experimentos, la siguiente función de la respuesta aceptada se ordena correctamente pero no cambia los valores.
fuente
Esto puede ayudar si le ha costado entender:
http://jsfiddle.net/ianjamieson/wmxn2ram/1/
fuente
En la función anterior, si solo comparamos cuando dos minúsculas valoran a y b, no tendremos el resultado bonito.
Ejemplo, si la matriz es [A, a, B, b, c, C, D, d, e, E] y usamos la función anterior, tenemos exactamente esa matriz. No ha cambiado nada.
Para obtener el resultado es [A, a, B, b, C, c, D, d, E, e], debemos comparar nuevamente cuando dos valores en minúscula son iguales:
fuente
Envolví la respuesta superior en un polyfill para poder llamar a .sortIgnoreCase () en matrices de cadenas
fuente
Envuelve tus cuerdas
/ /i
. Esta es una manera fácil de usar expresiones regulares para ignorar la carcasafuente