Ordenar objetos en una matriz alfabéticamente en una propiedad de la matriz

201

Digamos que tienes una clase de JavaScript como esta

var DepartmentFactory = function(data) {
    this.id = data.Id;
    this.name = data.DepartmentName;
    this.active = data.Active;
}

Digamos que luego crea una serie de instancias de esa clase y las almacena en una matriz

var objArray = [];
objArray.push(DepartmentFactory({Id: 1, DepartmentName: 'Marketing', Active: true}));
objArray.push(DepartmentFactory({Id: 2, DepartmentName: 'Sales', Active: true}));
objArray.push(DepartmentFactory({Id: 3, DepartmentName: 'Development', Active: true}));
objArray.push(DepartmentFactory({Id: 4, DepartmentName: 'Accounting', Active: true}));

Entonces ahora tendría una matriz de objetos creados por DepartmentFactory. ¿Cómo utilizaría el array.sort()método para ordenar esta matriz de objetos por la DepartmentNamepropiedad de cada objeto?

El array.sort()método funciona bien al ordenar una serie de cadenas

var myarray=["Bob", "Bully", "Amy"];
myarray.sort(); //Array now becomes ["Amy", "Bob", "Bully"]

Pero, ¿cómo hago para que funcione con una lista de objetos?

jdavis
fuente
Puede pasar una función de ordenación como primer argumento a .sort ().
Paul Tomblin
2
Como lo está utilizando DepartmentFactorycomo constructor, cree sus objetos utilizando new DepartmentFactory, de lo contrario, la matriz se llenará con un montón de undefinedvalores.
Anurag

Respuestas:

342

tendrías que hacer algo como esto:

objArray.sort(function(a, b) {
    var textA = a.DepartmentName.toUpperCase();
    var textB = b.DepartmentName.toUpperCase();
    return (textA < textB) ? -1 : (textA > textB) ? 1 : 0;
});

nota: al cambiar la mayúscula (a superior o inferior) se garantiza una clasificación que no distingue mayúsculas de minúsculas.

Omer Bokhari
fuente
3
He llegado a su respuesta 50 mil millones de veces porque nunca puedo recordar cómo hacer esto. FWIW, mi Linter siempre me informa de "paréntesis gratuitos en torno a la expresión": return (textA < textB) ? -1 : (textA > textB) ? 1 : 0;no voy a editar tu respuesta, esperando que al menos recuerde lo que
dice
Gracias por este Omer
Ted Fitzpatrick
Encontró un problema con este código. Use una combinación de letras mayúsculas y minúsculas. ex. credit_card_no y City. El código ordena la lista, pero las palabras que comienzan con 'c' no se agrupan.
Kedar
157

Para admitir unicode:

objArray.sort(function(a, b) {
   return a.DepartmentName.localeCompare(b.DepartmentName);
});
ron tornambe
fuente
77
Para una versión que no return a.DepartmentName.toLowerCase().localeCompare(b.DepartmentName.toLowerCase());
distinga
3
aprende algo nuevo todos los días: localeComparees genial y tiene todo el soporte del navegador para el primer argumento. ¡No está mal!
obzenner
44
@BenBarreth no hay razón para minúsculas las cadenas. el objetivo localeComparees desviar el trabajo de gestión de la lógica de clasificación y las peculiaridades de la configuración regional al sistema. Si hacer una ordenación que no distingue entre mayúsculas y minúsculas es normal para el entorno local, ya que está en inglés, esto se hará por usted: "Z" > 'a' // false "Z".localeCompare('a') // 1 si desea desviarse del valor predeterminado del entorno local, puede enviar anulaciones en los parámetros localesy options: developer.mozilla. org / es-US / docs / Web / JavaScript / Reference / ...
Jon z
12
var DepartmentFactory = function(data) {
    this.id = data.Id;
    this.name = data.DepartmentName;
    this.active = data.Active;
}

// use `new DepartmentFactory` as given below. `new` is imporatant

var objArray = [];
objArray.push(new DepartmentFactory({Id: 1, DepartmentName: 'Marketing', Active: true}));
objArray.push(new DepartmentFactory({Id: 2, DepartmentName: 'Sales', Active: true}));
objArray.push(new DepartmentFactory({Id: 3, DepartmentName: 'Development', Active: true}));
objArray.push(new DepartmentFactory({Id: 4, DepartmentName: 'Accounting', Active: true}));

function sortOn(property){
    return function(a, b){
        if(a[property] < b[property]){
            return -1;
        }else if(a[property] > b[property]){
            return 1;
        }else{
            return 0;   
        }
    }
}

//objArray.sort(sortOn("id")); // because `this.id = data.Id;`
objArray.sort(sortOn("name")); // because `this.name = data.DepartmentName;`
console.log(objArray);

demostración: http://jsfiddle.net/diode/hdgeH/

Diodo
fuente
9
// Sorts an array of objects "in place". (Meaning that the original array will be modified and nothing gets returned.)
function sortOn (arr, prop) {
    arr.sort (
        function (a, b) {
            if (a[prop] < b[prop]){
                return -1;
            } else if (a[prop] > b[prop]){
                return 1;
            } else {
                return 0;   
            }
        }
    );
}

//Usage example:

var cars = [
        {make:"AMC",        model:"Pacer",  year:1978},
        {make:"Koenigsegg", model:"CCGT",   year:2011},
        {make:"Pagani",     model:"Zonda",  year:2006},
        ];

// ------- make -------
sortOn(cars, "make");
console.log(cars);

/* OUTPUT:
AMC         : Pacer : 1978
Koenigsegg  : CCGT  : 2011
Pagani      : Zonda : 2006
*/



// ------- model -------
sortOn(cars, "model");
console.log(cars);

/* OUTPUT:
Koenigsegg  : CCGT  : 2011
AMC         : Pacer : 1978
Pagani      : Zonda : 2006
*/



// ------- year -------
sortOn(cars, "year");
console.log(cars);

/* OUTPUT:
AMC         : Pacer : 1978
Pagani      : Zonda : 2006
Koenigsegg  : CCGT  : 2011
*/
Beto
fuente
5

MANIFESTACIÓN

var DepartmentFactory = function(data) {
    this.id = data.Id;
    this.name = data.DepartmentName;
    this.active = data.Active;
}

var objArray = [];
objArray.push(new DepartmentFactory({Id: 1, DepartmentName: 'Marketing', Active: true}));
objArray.push(new DepartmentFactory({Id: 2, DepartmentName: 'Sales', Active: true}));
objArray.push(new DepartmentFactory({Id: 3, DepartmentName: 'Development', Active: true}));
objArray.push(new DepartmentFactory({Id: 4, DepartmentName: 'Accounting', Active: true}));

console.log(objArray.sort(function(a, b) { return a.name > b.name}));
qwertymk
fuente
2
objArray.sort( (a, b) => a.id.localeCompare(b.id, 'en', {'sensitivity': 'base'}));

Esto los ordena alfabéticamente Y no distingue entre mayúsculas y minúsculas. También es súper limpio y fácil de leer: D

Alissa
fuente
¡Mucho más elegante que la solución aceptada!
kano
Esta es también la única respuesta que menciona 'sensitivity': 'base', lo que hace una gran diferencia dependiendo de su aplicación de acuerdo con MDN .
phantomraa
2
objArray.sort((a, b) => a.DepartmentName.localeCompare(b.DepartmentName))
Neil
fuente
1

Hazlo asi

objArrayy.sort(function(a, b){
 var nameA=a.name.toLowerCase(), nameB=b.name.toLowerCase()
 if (nameA < nameB) //sort string ascending
  return -1
 if (nameA > nameB)
  return 1
 return 0 //default return value (no sorting)
});
console.log(objArray)
nickleefly
fuente
0

Aquí hay una función simple que puede usar para ordenar una matriz de objetos a través de sus propiedades; no importa si la propiedad es un tipo de cadena o entero, funcionará.

    var cars = [
        {make:"AMC",        model:"Pacer",  year:1978},
        {make:"Koenigsegg", model:"CCGT",   year:2011},
        {make:"Pagani",     model:"Zonda",  year:2006},
    ];

    function sortObjectsByProp(objectsArr, prop, ascending = true) {
        let objectsHaveProp = objectsArr.every(object => object.hasOwnProperty(prop));
        if(objectsHaveProp)    {
            let newObjectsArr = objectsArr.slice();
            newObjectsArr.sort((a, b) => {
                if(isNaN(Number(a[prop])))  {
                    let textA = a[prop].toUpperCase(),
                        textB = b[prop].toUpperCase();
                    if(ascending)   {
                        return textA < textB ? -1 : textA > textB ? 1 : 0;
                    } else {
                        return textB < textA ? -1 : textB > textA ? 1 : 0;
                    }
                } else {
                    return ascending ? a[prop] - b[prop] : b[prop] - a[prop];
                }
            });
            return newObjectsArr;
        }
        return objectsArr;
    }

    let sortedByMake = sortObjectsByProp(cars, "make"); // returns ascending order by its make;
    let sortedByYear = sortObjectsByProp(cars, "year", false); // returns descending order by its year,since we put false as a third argument;
    console.log(sortedByMake);
    console.log(sortedByYear);

Michael Norward
fuente
-1

Debe pasar una función que acepte dos parámetros, los compare y devuelva un número, por lo tanto, suponiendo que desea ordenarlos por ID, escribiría ...

objArray.sort(function(a,b) {
    return a.id-b.id;
});
// objArray is now sorted by Id
zconnelly13
fuente
55
Preguntó sobre la clasificación por DepartmentName, no Id.
Paul Tomblin
Intenté esto y esto no parece funcionar en columnas de cadena ... funcionó en una columna de fecha. Lo que funcionó fue la solución de @ omer-bokhari
tsando
-2

Después de intentarlo un poco e intentar hacer menos bucles como sea posible, terminé con esta solución:

Demo en codepen

const items = [
      {
        name: 'One'
      },
      {
        name: 'Maria is here'
      },
      {
        name: 'Another'
      },
      {
        name: 'Z with a z'
      },
      {
        name: '1 number'
      },
      {
        name: 'Two not a number'
      },
      {
        name: 'Third'
      },
      {
        name: 'Giant'
      }
    ];

    const sorted = items.sort((a, b) => {
      return a[name] > b[name];
    });

    let sortedAlphabetically = {};

    for(var item in sorted) {
      const firstLetter = sorted[item].name[0];
      if(sortedAlphabetically[firstLetter]) {
        sortedAlphabetically[firstLetter].push(sorted[item]);
      } else {
        sortedAlphabetically[firstLetter] = [sorted[item]]; 
      }
    }

    console.log('sorted', sortedAlphabetically);
Alexandre Magno Teles Zimerer
fuente
-3

Una respuesta simple:

objArray.sort(function(obj1, obj2) {
   return obj1.DepartmentName > obj2.DepartmentName;
});

Manera ES6:

objArray.sort((obj1, obj2) => {return obj1.DepartmentName > obj2.DepartmentName};

Si necesita hacerlo en minúsculas / mayúsculas, etc., simplemente haga eso y almacene ese resultado en una variable que compare esa variable. Ejemplo:

objArray.sort((obj1, obj2) => {
   var firstObj = obj1.toLowerCase();
   var secondObj = obj2.toLowerCase();
   return firstObj.DepartmentName > secondObj.DepartmentName;
});
Masha
fuente