Ordinare gli oggetti in un array in ordine alfabetico su una proprietà dell'array


201

Supponiamo che tu abbia una classe JavaScript come questa

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

Supponiamo che tu crei un numero di istanze di quella classe e le memorizzi in un array

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}));

Quindi ora avrei una serie di oggetti creati da DepartmentFactory. Come farei usando il array.sort()metodo per ordinare questo array di oggetti in base alla DepartmentNameproprietà di ciascun oggetto?

Il array.sort()metodo funziona perfettamente quando si ordina una matrice di stringhe

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

Ma come faccio a farlo funzionare con un elenco di oggetti?


È possibile passare una funzione di ordinamento come primo argomento a .sort ().
Paul Tomblin,

2
Dal momento che stai usando DepartmentFactorycome costruttore, crea i suoi oggetti usando new DepartmentFactory, altrimenti l'array verrà riempito con un mucchio di undefinedvalori.
Anurag,

Risposte:


342

dovresti fare qualcosa del genere:

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

nota: la modifica del maiuscolo (in alto o in basso) garantisce un ordinamento insensibile al maiuscolo / minuscolo.


3
Sono arrivato alla tua risposta 50 gazillion volte perché non riesco mai a ricordare come farlo. FWIW, la mia Linter mi informa sempre di "parentesi gratuite attorno all'espressione": return (textA < textB) ? -1 : (textA > textB) ? 1 : 0;non modificherò la tua risposta, tendendo la speranza almeno mi ricorderò della cosa che linting :)
Michael Tranchida,

Grazie per questo Omer
Ted Fitzpatrick il

Trovato un problema con questo codice. Utilizzare una combinazione di lettere maiuscole e minuscole. ex. credit_card_no e City. Il codice ordina l'elenco ma le parole che iniziano con 'c' non sono raggruppate insieme.
Kedar,

157

Per supportare unicode:

objArray.sort(function(a, b) {
   return a.DepartmentName.localeCompare(b.DepartmentName);
});

7
Per una versione senza distinzione tra maiuscole e minuscole, utilizzare quanto segue alla riga 2:return a.DepartmentName.toLowerCase().localeCompare(b.DepartmentName.toLowerCase());
Ben Barreth,

3
impara qualcosa di nuovo ogni giorno - localeCompareè interessante e ha tutto il supporto del browser per il primo argomento. Non male!
obzenner,

4
@BenBarreth non c'è motivo per minuscole le stringhe. il punto principale localeCompareè quello di deviare il lavoro di gestione della logica di ordinamento e delle stranezze locali al sistema. Se fare un ordinamento senza distinzione tra maiuscole e minuscole è normale per le "Z" > 'a' // false "Z".localeCompare('a') // 1 impostazioni locali, poiché è in inglese, questo verrà fatto per te: se desideri deviare dalle impostazioni predefinite delle impostazioni locali, puoi inviare le sostituzioni con i parametri localese options: developer.mozilla. org / it-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);

demo: http://jsfiddle.net/diode/hdgeH/


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
*/

5

DEMO

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}));

2
objArray.sort( (a, b) => a.id.localeCompare(b.id, 'en', {'sensitivity': 'base'}));

Questo li ordina alfabeticamente E non fa distinzione tra maiuscole e minuscole. È anche super pulito e di facile lettura: D


Molto più elegante della soluzione accettata!
Kano,

Questa è anche l'unica risposta che menziona 'sensitivity': 'base', che fa una grande differenza a seconda della tua applicazione secondo MDN .
Phantomraa

2
objArray.sort((a, b) => a.DepartmentName.localeCompare(b.DepartmentName))

1

Fai cosi

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)

0

Ecco una semplice funzione che puoi usare per ordinare array di oggetti attraverso le loro proprietà; non importa se la proprietà è un tipo di stringa o intero, funzionerà.

    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);


-1

Devi passare una funzione che accetta due parametri, li confronta e restituisce un numero, quindi supponendo che tu volessi ordinarli per ID scriverai ...

objArray.sort(function(a,b) {
    return a.id-b.id;
});
// objArray is now sorted by Id

5
Ha chiesto informazioni sull'ordinamento per DepartmentName, non per ID.
Paul Tomblin,

Ho provato questo e questo non sembra funzionare su colonne stringa ... ha funzionato su una colonna data. Ciò che ha funzionato è stata la soluzione di @ omer-bokhari
tsando

-2

Dopo aver provato un po 'su questo, e cercando di fare meno loop possibili, ho finito con questa soluzione:

Demo su 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);

-3

Una semplice risposta:

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

Modo ES6:

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

Se è necessario renderlo minuscolo / maiuscolo ecc., Basta farlo e archiviare quel risultato in una variabile piuttosto che confrontarla. Esempio:

objArray.sort((obj1, obj2) => {
   var firstObj = obj1.toLowerCase();
   var secondObj = obj2.toLowerCase();
   return firstObj.DepartmentName > secondObj.DepartmentName;
});
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.