Ordenar matriz de objetos por valor de propiedad de cadena

Resuelto Tyrone Slothrop asked hace 15 años • 61 respuestas

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_nomen 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?

Tyrone Slothrop avatar Jul 15 '09 10:07 Tyrone Slothrop
Aceptado

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
Wogan avatar Jul 15 '2009 03:07 Wogan

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");
Ege Özcan avatar Jan 21 '2011 15:01 Ege Özcan

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)
});
Vlad Bezden avatar Jan 29 '2016 19:01 Vlad Bezden