Ordenar matriz de objetos por valor de propiedad de cadena
Tengo una variedad de objetos JavaScript:
var objs = [
{ first_nom: 'Laszlo', last_nom: 'Jamf' },
{ first_nom: 'Pig', last_nom: 'Bodine' },
{ first_nom: 'Pirate', last_nom: 'Prentice' }
];
¿Cómo puedo ordenarlos por el valor de last_nom
en JavaScript?
Lo sé sort(a,b)
, pero eso solo parece funcionar en cadenas y números. ¿ Necesito agregar un toString()
método a mis objetos?
Es bastante fácil escribir su propia función de comparación:
function compare( a, b ) {
if ( a.last_nom < b.last_nom ){
return -1;
}
if ( a.last_nom > b.last_nom ){
return 1;
}
return 0;
}
objs.sort( compare );
O en línea ( c/o Marco Demaio ):
objs.sort((a,b) => (a.last_nom > b.last_nom) ? 1 : ((b.last_nom > a.last_nom) ? -1 : 0))
O simplificado para numérico ( c/o Andre Figueiredo ):
objs.sort((a,b) => a.last_nom - b.last_nom); // b - a for reverse sort
También puedes crear una función de clasificación dinámica que ordene los objetos por el valor que pasas:
function dynamicSort(property) {
var sortOrder = 1;
if(property[0] === "-") {
sortOrder = -1;
property = property.substr(1);
}
return function (a,b) {
/* next line works with strings and numbers,
* and you may want to customize it to your needs
*/
var result = (a[property] < b[property]) ? -1 : (a[property] > b[property]) ? 1 : 0;
return result * sortOrder;
}
}
Entonces puedes tener una variedad de objetos como este:
var People = [
{Name: "Name", Surname: "Surname"},
{Name:"AAA", Surname:"ZZZ"},
{Name: "Name", Surname: "AAA"}
];
...y funcionará cuando lo hagas:
People.sort(dynamicSort("Name"));
People.sort(dynamicSort("Surname"));
People.sort(dynamicSort("-Surname"));
En realidad esto ya responde la pregunta. La parte siguiente está escrita porque muchas personas se comunicaron conmigo quejándose de que no funciona con múltiples parámetros .
Múltiples parámetros
Puede utilizar la siguiente función para generar funciones de clasificación con múltiples parámetros de clasificación.
function dynamicSortMultiple() {
/*
* save the arguments object as it will be overwritten
* note that arguments object is an array-like object
* consisting of the names of the properties to sort by
*/
var props = arguments;
return function (obj1, obj2) {
var i = 0, result = 0, numberOfProperties = props.length;
/* try getting a different result from 0 (equal)
* as long as we have extra properties to compare
*/
while(result === 0 && i < numberOfProperties) {
result = dynamicSort(props[i])(obj1, obj2);
i++;
}
return result;
}
}
Lo que te permitiría hacer algo como esto:
People.sort(dynamicSortMultiple("Name", "-Surname"));
Matriz de subclases
Para los afortunados que pueden utilizar ES6, que permite ampliar los objetos nativos:
class MyArray extends Array {
sortBy(...args) {
return this.sort(dynamicSortMultiple(...args));
}
}
Eso permitiría esto:
MyArray.from(People).sortBy("Name", "-Surname");
En ES6/ES2015 o posterior puedes hacerlo de esta manera:
objs.sort((a, b) => a.last_nom.localeCompare(b.last_nom));
Antes de ES6/ES2015
objs.sort(function(a, b) {
return a.last_nom.localeCompare(b.last_nom)
});