Estoy tratando de ordenar una matriz con objetos basados en múltiples atributos. Es decir, si el primer atributo es el mismo entre dos objetos, se debe utilizar un segundo atributo para comparar los dos objetos. Por ejemplo, considere la siguiente matriz:
var patients = [
[{name: 'John', roomNumber: 1, bedNumber: 1}],
[{name: 'Lisa', roomNumber: 1, bedNumber: 2}],
[{name: 'Chris', roomNumber: 2, bedNumber: 1}],
[{name: 'Omar', roomNumber: 3, bedNumber: 1}]
];
Ordenándolos por el roomNumber
atributo, usaría el siguiente código:
var sortedArray = _.sortBy(patients, function(patient) {
return patient[0].roomNumber;
});
Esto funciona bien, pero ¿cómo procedo para que 'John' y 'Lisa' se clasifiquen correctamente?
fuente
[0]
indexador es necesario porque en el ejemplo originalpatients
es una matriz de matrices. Esta es también la razón por la que la "solución más simple" en la publicación del blog mencionada en otro comentario no funcionará aquí.Aquí hay un truco hacky que a veces uso en estos casos: combine las propiedades de tal manera que el resultado sea ordenable:
Sin embargo, como dije, eso es bastante complicado. Para hacer esto correctamente, probablemente desee utilizar el
sort
método principal de JavaScript :Por supuesto, esto ordenará su matriz en su lugar. Si desea una copia ordenada (como
_.sortBy
le daría), primero clone la matriz:Por aburrimiento, acabo de escribir una solución general (para ordenar por cualquier número arbitrario de claves) para esto también: eche un vistazo .
fuente
return [patient[0].roomNumber, patient[0].name];
suficiente sin eljoin
?compare
los valores de identificador que no son valores primitivos -undefined
,null
u objetos lisos?Sé que llego tarde a la fiesta, pero quería agregar esto para aquellos que necesitan una solución más limpia y rápida que los que ya sugirieron. Puede encadenar las llamadas sortBy en el orden de la propiedad menos importante a la propiedad más importante. En el siguiente código, creo una nueva matriz de pacientes ordenados por Nombre dentro RoomNumber de la matriz original llamada pacientes .
fuente
por cierto, su inicializador para pacientes es un poco extraño, ¿no? ¿Por qué no inicializa esta variable como esta? Como una verdadera matriz de objetos, puede hacerlo usando _.flatten () y no como una matriz de matrices de un solo objeto, tal vez sea un problema de error tipográfico):
Ordené la lista de manera diferente y agregué a Kiko a la cama de Lisa; solo por diversión y ver qué cambios se harían ...
inspeccione ordenado y verá esto
entonces mi respuesta es: use una matriz en su función de devolución de llamada, esto es bastante similar a la respuesta de Dan Tao , simplemente olvido la combinación (tal vez porque eliminé la matriz de matrices de elementos únicos :))
Usando su estructura de datos, entonces sería :
y una carga de prueba sería interesante ...
fuente
Ninguna de estas respuestas es ideal como método de propósito general para usar varios campos en una clasificación. Todos los enfoques anteriores son ineficaces ya que requieren ordenar la matriz varias veces (lo que, en una lista lo suficientemente grande, podría ralentizar mucho las cosas) o generan grandes cantidades de objetos basura que la máquina virtual necesitará limpiar (y, en última instancia, ralentizar el programa abajo).
Aquí hay una solución que es rápida, eficiente, permite fácilmente la clasificación inversa y se puede utilizar con
underscore
olodash
, o directamente conArray.sort
La parte más importante es el
compositeComparator
método, que toma una matriz de funciones de comparación y devuelve una nueva función de comparación compuesta.También necesitará una función de comparación para comparar los campos por los que desea ordenar. La
naturalSort
función creará un comparador dado un campo en particular. Escribir un comparador para la clasificación inversa también es trivial.(Todo el código hasta ahora es reutilizable y podría guardarse en el módulo de utilidad, por ejemplo)
A continuación, debe crear el comparador compuesto. Para nuestro ejemplo, se vería así:
Esto ordenará por número de habitación, seguido del nombre. Agregar criterios de clasificación adicionales es trivial y no afecta el rendimiento de la clasificación.
Devuelve lo siguiente
La razón por la que prefiero este método es que permite una clasificación rápida en un número arbitrario de campos, no genera mucha basura ni realiza una concatenación de cadenas dentro de la clasificación y se puede usar fácilmente para que algunas columnas se clasifiquen al revés mientras que las columnas de orden usan natural ordenar.
fuente
Ejemplo simple de http://janetriley.net/2014/12/sort-on-multiple-keys-with-underscores-sortby.html (cortesía de @MikeDevenney)
Código
Con sus datos
fuente
Quizás underscore.js o simplemente los motores de Javascript son diferentes ahora que cuando se escribieron estas respuestas, pero pude resolver esto simplemente devolviendo una matriz de las claves de clasificación.
En acción, vea este violín: https://jsfiddle.net/mikeular/xenu3u91/
fuente
Solo devuelve una matriz de propiedades que desea ordenar:
Sintaxis de ES6
Sintaxis de ES5
Esto no tiene los efectos secundarios de convertir un número en una cadena.
fuente
Puede concatenar las propiedades por las que desea ordenar en el iterador:
o algo equivalente.
NOTA: Dado que está convirtiendo el atributo numérico roomNumber en una cadena, tendría que hacer algo si tuviera números de habitación> 10. De lo contrario, 11 vendrá antes que 2. Puede rellenar con ceros a la izquierda para resolver el problema, es decir, 01 en lugar de 1.
fuente
Creo que será mejor que uses en
_.orderBy
lugar desortBy
:fuente
_.orderBy
funciona, pero es un método de la biblioteca lodash, no de subrayado: lodash.com/docs/4.17.4#orderBy lodash es principalmente un reemplazo directo del subrayado, por lo que podría ser apropiado para el OP.Si está usando Angular, puede usar su filtro numérico en el archivo html en lugar de agregar cualquier controlador JS o CSS. Por ejemplo:
En ese ejemplo, si val = 1234567, se mostrará como
Ejemplo y orientación adicional en: https://docs.angularjs.org/api/ng/filter/number
fuente