Tengo una lista de objetos que deseo ordenar según un campo attr
de tipo cadena. Traté de usar-
list.sort(function (a, b) {
return a.attr - b.attr
})
pero descubrió que -
no parece funcionar con cadenas en JavaScript. ¿Cómo puedo ordenar una lista de objetos basada en un atributo con tipo cadena?
javascript
string
airportyh
fuente
fuente
JavaScript case insensitive string comparison
en stackoverflow.com/questions/2140627/…Javascript : remove accents/diacritics in strings
el stackoverflow.com/questions/990904/...Respuestas:
Use
String.prototype.localeCompare
a por su ejemplo:Obligamos a a.attr a ser una cadena para evitar excepciones.
localeCompare
ha sido compatible desde Internet Explorer 6 y Firefox 1. También puede ver el siguiente código utilizado que no respeta una configuración regional:fuente
localeCompare()
no se encuentra con este problema, pero no entiende los números, por lo que obtendrá ["1", "10", "2"] como con las comparaciones de clasificación en la mayoría de los idiomas. si desea ordenar por su interfaz de usuario, busque en el algoritmo de ordenación alfanumérico / natural stackoverflow.com/questions/4340227/… o stackoverflow.com/questions/4321829/…localeCompare()
solo es compatible con los navegadores modernos: IE11 + en el momento de la escritura, consulte developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…localeCompare()
volver a muchas versiones, pero no admite especificar la configuración regional hasta la versión 11. Tenga en cuenta también las preguntas a las que Dead.Rabit se vinculó.Una respuesta actualizada (octubre de 2014)
Estaba realmente molesto por este orden de clasificación natural de cadenas, así que me tomé bastante tiempo para investigar este problema. Espero que esto ayude.
Larga historia corta
localeCompare()
el soporte de personajes es rudo, solo úsalo. Como se señalóShog9
, la respuesta a su pregunta es:Se encontraron errores en todas las implementaciones de "orden de clasificación de cadena natural" de javascript personalizado
Hay bastantes implementaciones personalizadas por ahí, que intentan hacer una comparación de cadenas más precisamente llamada "orden de clasificación de cadena natural"
Al "jugar" con estas implementaciones, siempre noté alguna elección extraña de "orden de clasificación natural", o más bien errores (u omisiones en los mejores casos).
Por lo general, los caracteres especiales (espacio, guión, ampersand, corchetes, etc.) no se procesan correctamente.
Luego los encontrará mezclados en diferentes lugares, generalmente eso podría ser:
Cuando uno hubiera esperado que los caracteres especiales se "agruparan" en un solo lugar, excepto por el carácter especial de espacio (que siempre sería el primer carácter). Es decir, todos antes de los números, o todos entre números y letras (minúsculas y mayúsculas están "juntas" una tras otra), o todas después de las letras.
Mi conclusión es que todos no pueden proporcionar un orden consistente cuando comienzo a agregar caracteres apenas inusuales (es decir, caracteres con signos diacríticos o caracteres como guión, signo de exclamación, etc.).
Investigación sobre las implementaciones personalizadas:
Natural Compare Lite
https://github.com/litejs/natural-compare-lite : falla al ordenar consistentemente https://github.com/litejs/natural-compare-lite/issues/1 y http://jsbin.com/bevututodavi/ 1 / edit? Js, consola , ordenación básica de caracteres latinos http://jsbin.com/bevututodavi/5/edit?js,consoleNatural Sort
https://github.com/javve/natural-sort : falla al ordenar de manera consistente, vea el problema https://github.com/javve/natural-sort/issues/7 y vea los caracteres latinos básicos que ordenan http: // jsbin. com / cipimosedoqe / 3 / edit? js, consolaJavascript Natural Sort
https://github.com/overset/javascript-natural-sort : parece bastante descuidado desde febrero de 2012, falla al ordenar de manera consistente, vea el problema https://github.com/overset/javascript-natural-sort/issues/16Alphanum
http://www.davekoelle.com/files/alphanum.js , falla en la clasificación de forma consistente, consulte http://jsbin.com/tuminoxifuyo/1/edit?js,consoleImplementaciones nativas de "orden de cadena natural" de los navegadores a través de
localeCompare()
localeCompare()
IE6 + admite la implementación más antigua (sin los argumentos locales y de opciones), consulte http://msdn.microsoft.com/en-us/library/ie/s4esdbwz(v=vs.94).aspx (desplácese hacia abajo para ubicaleCompare ( ) método). EllocaleCompare()
método incorporado hace un trabajo mucho mejor en la clasificación, incluso caracteres internacionales y especiales. El único problema con ellocaleCompare()
método es que "la configuración regional y el orden de clasificación utilizados dependen completamente de la implementación". En otras palabras, cuando se usa localeCompare como stringOne.localeCompare (stringTwo): Firefox, Safari, Chrome e IE tienen un orden de clasificación diferente para las cadenas.Investigación sobre las implementaciones nativas del navegador:
Dificultad del "orden de clasificación natural de la cuerda"
Implementar un algoritmo sólido (es decir: consistente pero que también cubre una amplia gama de caracteres) es una tarea muy difícil. UTF8 contiene más de 2000 caracteres y cubre más de 120 scripts (idiomas) . Finalmente, hay algunas especificaciones para estas tareas, se llama "Algoritmo de clasificación Unicode", que se puede encontrar en http://www.unicode.org/reports/tr10/ . Puede encontrar más información sobre esto en esta pregunta que publiqué /software/257286/is-there-any-language-agnostic-specification-for-string-natural-sorting-order
Conclusión final
Por lo tanto, teniendo en cuenta el nivel actual de soporte proporcionado por las implementaciones personalizadas de JavaScript que encontré, probablemente nunca veremos nada que se acerque a todos estos caracteres y scripts (idiomas). Por lo tanto, preferiría usar el método nativo localeCompare () de los navegadores. Sí, tiene el inconveniente de no ser coherente en todos los navegadores, pero las pruebas básicas muestran que cubre una gama mucho más amplia de caracteres, lo que permite órdenes de clasificación sólidas y significativas.
Entonces, como se señaló
Shog9
, la respuesta a su pregunta es:Otras lecturas:
Gracias a la buena respuesta de Shog9, que me puso en la dirección "correcta", creo
fuente
Respuesta (en Modern ECMAScript)
O
Descripción
Lanzar un valor booleano a un número produce lo siguiente:
true
->1
false
->0
Considere tres posibles patrones:
(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
Entonces, estas lógicas son equivalentes a las funciones típicas de comparación de clasificación.
fuente
localeCompare
y la comparación estándar producen resultados diferentes. Cual esperas["A", "b", "C", "d"].sort((a, b) => a.localeCompare(b))
las clases en el orden alfabético de mayúsculas y minúsculas, mientras que["A", "b", "C", "d"].sort((a, b) => (a > b) - (a < b))
lo hace con el fin de punto de códigoDebe usar> o <y == aquí. Entonces la solución sería:
fuente
Función de flecha ternaria anidada
fuente
Como las cadenas se pueden comparar directamente en JavaScript, esto hará el trabajo
la resta en una función de clasificación se usa solo cuando se desea una clasificación no alfabética (numérica) y, por supuesto, no funciona con cadenas
fuente
Me había preocupado por esto durante mucho tiempo, así que finalmente investigué esto y le di esta razón larga y sin aliento de por qué las cosas son como son.
De la especificación :
Así que ahora vamos a 11.9.6
Eso es. El operador triple igual aplicado a las cadenas devuelve verdadero si los argumentos son exactamente las mismas cadenas (la misma longitud y los mismos caracteres en las posiciones correspondientes).
Por
===
lo tanto , funcionará en los casos en que intentemos comparar cadenas que podrían haber llegado de diferentes fuentes, pero que sabemos que eventualmente tendrán los mismos valores, un escenario lo suficientemente común para cadenas en línea en nuestro código. Por ejemplo, si tenemos una variable llamadaconnection_state
y deseamos saber en cuál de los siguientes estados se['connecting', 'connected', 'disconnecting', 'disconnected']
encuentra en este momento, podemos usar directamente===
.Pero hay más. Justo arriba de 11.9.4, hay una breve nota:
Hmm ¿Ahora que? Las cadenas obtenidas externamente pueden, y muy probablemente serán, unicodey extrañas, y nuestro gentil
===
no les hará justicia. En vienelocaleCompare
al rescate:Podemos irnos a casa ahora.
tl; dr;
Para comparar cadenas en javascript, use
localeCompare
; si sabe que las cadenas no tienen componentes que no sean ASCII porque son, por ejemplo, constantes internas del programa, entonces===
también funcionan.fuente
En su operación en su pregunta inicial, está realizando la siguiente operación:
Por lo tanto, suponiendo que se trata de números (es decir, item1.attr = "1", item2.attr = "2") Aún puede utilizar el operador "===" (u otros evaluadores estrictos) siempre que se asegure el tipo. Lo siguiente debería funcionar:
Si son alphaNumeric, entonces use localCompare ().
fuente
Cómo funcionan las muestras:
fuente
fuente
fuente