Ordina l'array per nome (in ordine alfabetico) in Javascript


647

Ho un array (vedi sotto per un oggetto nell'array) che devo ordinare per nome usando JavaScript. Come posso farlo?

var user = {
   bio: null,
   email:  "user@domain.com",
   firstname: "Anna",
   id: 318,
   lastAvatar: null,
   lastMessage: null,
   lastname: "Nickson",
   nickname: "anny"
};

Risposte:


1068

Supponiamo di avere un array users. È possibile utilizzare users.sorte passare una funzione che accetta due argomenti e li confronta (comparatore)

Dovrebbe tornare

  • qualcosa di negativo se il primo argomento è inferiore al secondo (dovrebbe essere posizionato prima del secondo nell'array risultante)
  • qualcosa di positivo se il primo argomento è maggiore (dovrebbe essere inserito dopo il secondo)
  • 0 se quei due elementi sono uguali.

Nel nostro caso se due elementi sono ae bvogliamo confrontare a.firstnameeb.firstname

Esempio:

users.sort(function(a, b){
    if(a.firstname < b.firstname) { return -1; }
    if(a.firstname > b.firstname) { return 1; }
    return 0;
})

Questo codice funzionerà con qualsiasi tipo.

Si noti che nella "vita reale" ™ spesso si desidera ignorare il caso, ordinare correttamente i segni diacritici, simboli strani come ß, ecc. Quando si confrontano le stringhe, quindi è consigliabile utilizzarle localeCompare. Vedi altre risposte per chiarezza.


5
Friggin fantastico ... Sto ordinando un nodelist per id ... funziona come un fascino. Grazie mille!
Cody,

74
Per quelli che arrivano in un secondo momento, la risposta di Mrchief è migliore perché non fa distinzione tra maiuscole e minuscole.
mlienau

25
@mlienau, non lo definirei migliore o peggiore. È solo un altro
RiaD

19
@RiaD abbastanza giusto. Non riesco proprio a pensare a molti casi di smistamento alfabetico degli oggetti, incluso l'alloggiamento, in cui "Zebra" appare nell'elenco prima di "mela", sarebbe molto utile.
mlienau,

15
Questo codice funziona solo su paesi di lingua inglese. In altri paesi dovresti usare la risposta di ovunccetin conlocaleCompare .
Spoike,

546

Il codice più breve possibile con ES6!

users.sort((a, b) => a.firstname.localeCompare(b.firstname))

String.prototype.localeCompare () il supporto di base è universale!


27
Di gran lunga la migliore risposta se vivi nel 2017
nathanbirrell l'

52
Migliore risposta anche se vivi nel 2018;)
Simone

49
Probabilmente sarà anche la migliore risposta per il 2019.
Ahmad Maleki,

23
2020 forse? o naaa?
kspearrin,

15
ah amico, nel 2030 la terra si allaga e questo funziona solo in montagna.
Starfs,

343

Qualcosa come questo:

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

43
Quando l'ordinamento di stringhe 'toLowerCase ()' è molto importante, le lettere maiuscole potrebbero influire sull'ordinamento.
MarzSocks

3
Nel caso in cui qualcun altro si stia chiedendo che impatto ha toLowerCase, non è molto:'a'>'A' //true 'z'>'a' //true 'A'>'z' //false
Semplificazione del

14
@SimplGy Direi che il suo impatto è un po 'più di quello che gli stai dando credito. Ad esempio, come indicato nei commenti alla risposta accettata, è importante sapere se la funzione di ordinamento ordinerà la stringa 'Zebra'più in alto della stringa 'apple', cosa che farà se non si utilizza .toLowerCase().
PrinceTyke,

1
@PrinceTyke sì, è un buon caso, amico. 'Z' < 'a' // truee'z' < 'a' // false
Semplicemente il

2
Tutti i punti validi e direi che l'ordinamento è sempre un tipo di cosa "dipende". Se stai ordinando per nome, la distinzione tra maiuscole e minuscole potrebbe non avere importanza. In altri casi potrebbe. Indipendentemente da ciò, penso che l'adozione della propria situazione specifica non sia difficile una volta che si ottiene l'idea di base.
Mrchief,

336

Se le stringhe confrontate contengono caratteri unicode puoi utilizzare la localeComparefunzione di Stringclasse come la seguente:

users.sort(function(a,b){
    return a.firstname.localeCompare(b.firstname);
})

3
String.localeCompare non supporta Safari e IE <11 :)
CORSAIR l'

13
@CORSAIR è supportato, è solo il secondo e il terzo parametro che non sono supportati.
Codler

6
@CORSAIR l'uso nell'esempio è supportato in tutti i principali browser IE: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… . LocaleCompare tiene conto anche della capitalizzazione, quindi penso che questa implementazione debba essere considerata la migliore pratica.
Matt Jensen,

9
users.sort ((a, b) => a.firstname.localeCompare (b.firstname)) // Versione breve n dolce ES6!
Nachiketha,

4
carri armati nell'uso ES6users.sort((a, b) => a.name.localeCompare(b.name))
Mohmmad Ebrahimi Aval

32

Nice little ES6 one liner:

users.sort((a, b) => a.firstname !== b.firstname ? a.firstname < b.firstname ? -1 : 1 : 0);

2
Questo è incompleto poiché non gestisce correttamente gli stessi valori.
Karl-Johan Sjögren,

1
Naturalmente, grazie per averlo individuato, ho aggiunto un controllo per i valori corrispondenti
Sam Logan,

non male suppongo che se lo vuoi davvero tutto su una riga, i ternari nidificati diventano confusi per leggibilità però
russter

24

È possibile utilizzare localeCompare ma è necessario controllare anche le chiavi per i valori di falso

Il codice seguente non funzionerà se in una voce manca lname.

obj.sort((a, b) => a.lname.localeCompare(b.lname))

Quindi dobbiamo verificare il valore del falso come di seguito

let obj=[
{name:'john',lname:'doe',address:'Alaska'},
{name:'tom',lname:'hopes',address:'California'},
{name:'harry',address:'Texas'}
]
let field='lname';
console.log(obj.sort((a, b) => (a[field] || "").toString().localeCompare((b[field] || "").toString())));

O

possiamo usare lodash, è molto semplice. Rileverà i valori restituiti, ovvero se il numero o la stringa e eseguirà l'ordinamento di conseguenza.

import sortBy from 'lodash/sortBy';
sortBy(obj,'name')

https://lodash.com/docs/4.17.5#sortBy


2
Lodash è abbastanza pulito! Non ne avevo mai sentito parlare prima. Funziona alla grande!
Derk Jan Speelman,

15

underscorejs offre la bellissima funzione _.sortBy:

_.sortBy([{a:1},{a:3},{a:2}], "a")

oppure puoi utilizzare una funzione di ordinamento personalizzata:

_.sortBy([{a:"b"},{a:"c"},{a:"a"}], function(i) {return i.a.toLowerCase()})

2
il secondo esempio riguarda la restituzione di stringhe. Non sortByrilevano i valori restituiti sono stringhe ed esegue quindi un ordinamento alfabetico? Grazie
superjos il

12

Nel caso in cui stiamo ordinando nomi o qualcosa con caratteri speciali, come ñ o áéíóú (beni comuni in spagnolo), potremmo usare i parametri locali ( es in spagnolo in questo caso) e opzioni come questa:

let user = [{'firstname': 'Az'},{'firstname': 'Áb'},{'firstname':'ay'},{'firstname': 'Ña'},{'firstname': 'Nz'},{'firstname': 'ny'}];


user.sort((a, b) => a.firstname.localeCompare(b.firstname, 'es', {sensitivity: 'base'}))


console.log(user)

Le opzioni locali locali possono essere trovate qui in iana , es (spagnolo), de (tedesco), fr (francese). A proposito di base di sensibilità significa:

Solo le stringhe che differiscono nelle lettere di base si equivalgono. Esempi: a ≠ b, a = á, a = A.


8

Fondamentalmente puoi ordinare le matrici con il metodo sort, ma se vuoi ordinare gli oggetti, devi passare la funzione per ordinare il metodo dell'array, quindi ti darò un esempio usando l'array

user = [{
bio: "<null>",
email: "user@domain.com",
firstname: 'Anna',
id: 318,
"last_avatar": "<null>",
"last_message": "<null>",
lastname: 'Nickson',
nickname: 'anny'
},
{
bio: "<null>",
email: "user@domain.com",
firstname: 'Senad',
id: 318,
"last_avatar": "<null>",
"last_message": "<null>",
lastname: 'Nickson',
nickname: 'anny'
},
{
bio: "<null>",
email: "user@domain.com",
firstname: 'Muhamed',
id: 318,
"last_avatar": "<null>",
"last_message": "<null>",
lastname: 'Nickson',
nickname: 'anny'
}];

var ar = user.sort(function(a, b)
{
  var nA = a.firstname.toLowerCase();
  var nB = b.firstname.toLowerCase();

  if(nA < nB)
    return -1;
  else if(nA > nB)
    return 1;
 return 0;
});

perché restituire 0 alla fine?
Nobita,

=, quando le stringhe sono uguali
Senad Meškin,

ma in quel caso non dovrebbe elseessere rimosso? Altrimenti return 0non verrà mai letto
Nobita il

2
che non è "altro", è "altro se"
Senad Meškin,


8

Una notazione più compatta:

user.sort(function(a, b){
    return a.firstname === b.firstname ? 0 : a.firstname < b.firstname ? -1 : 1;
})

è più compatto ma viola il suo contratto: sign(f(a, b)) =-sign(f(b, a))(per a = b)
RiaD

3
ritorno a.firstname == b.firstnamedovrebbe usare ===per completezza
puiu

6

anche per asec e sort, puoi usare questo: supponiamo di avere un SortType variabile che specifica l'ordinamento crescente o l'ordinamento decrescente che desideri:

 users.sort(function(a,b){
            return   sortType==="asc"? a.firstName.localeCompare( b.firstName): -( a.firstName.localeCompare(  b.firstName));
        })

5

Una funzione generalizzata può essere scritta come di seguito

    function getSortedData(data, prop, isAsc) {
        return data.sort((a, b) => (a[prop] < b[prop] ? -1 : 1) * (isAsc ? 1 : -1));
   }

puoi passare i seguenti parametri

  1. I dati che desideri ordinare
  2. La proprietà nei dati da essa deve essere ordinata
  3. L'ultimo parametro è di tipo booleano. Controlla se si desidera ordinare in ordine crescente o decrescente

4

provare

users.sort((a,b)=> (a.firstname>b.firstname)*2-1)


2
la funzione di ordinamento dovrebbe restituire -1,0,1. questo restituisce solo -1,1.
Radu Luncasu,

@RaduLuncasu: è possibile fornire dati di test (array utenti) che dimostrano che la soluzione di cui sopra produce risultati errati? (per quanto ne so, mancare lo zero non è un problema)
Kamil Kiełczewski,

Se compareFunction (a, b) restituisce 0, lascia aeb invariati l'uno rispetto all'altro, ma ordinati in base a tutti i diversi elementi.
Radu Luncasu,


@RaduLuncasu ok, ma queste informazioni non significano che zero è obbligatorio. Il modo migliore per dimostrarlo è preparare dati che non funzionano - ma per quanto ne so è impossibile - ad es.[9,8,7,6,5,1,2,3].sort((a,b) => a<b ? -1 : 1)
Kamil Kiełczewski

3

Puoi usarlo per gli oggetti

transform(array: any[], field: string): any[] {
return array.sort((a, b) => a[field].toLowerCase() !== b[field].toLowerCase() ? a[field].toLowerCase() < b[field].toLowerCase() ? -1 : 1 : 0);}

2

in parole semplici puoi usare questo metodo

users.sort(function(a,b){return a.firstname < b.firstname ? -1 : 1});

1

È possibile utilizzare il metodo array incorporato - sort. Questo metodo utilizza un metodo di callback come parametro



    // custom sort function to be passed as param/callback to the Array's sort method
    function myCustomSort(a, b) {
        return (a.toLowerCase() > b.toLowerCase()) ? 1 : -1;
    }

    // Actual method to be called by entity that needs sorting feature
    function sortStrings() {
        var op = Array.prototype.sort.call(arguments, myCustomSort);
    }

    // Testing the implementation
    var sortedArray = sortStrings("Burger", "Mayo1", "Pizza", "boxes", "Apples", "Mayo");
    console.log(sortedArray); //["Apples", "boxes", "Burger", "Mayo", "Mayo1", "Pizza"]


Punti chiave da notare per comprendere questo codice.

  1. Il metodo personalizzato, in questo caso, myCustomSortdovrebbe restituire +1 o -1 per ogni confronto di coppie di elementi (dall'array di input).
  2. Utilizzare toLowerCase()/ toUpperCase()nel metodo di callback di ordinamento personalizzato in modo che la differenza tra maiuscole e minuscole non influisca sulla correttezza del processo di ordinamento.

Spero che questa sia una spiegazione abbastanza chiara. Sentiti libero di commentare se pensi che siano necessarie maggiori informazioni.

Saluti!


Non è una risposta corretta perché esegue solo meno e maggiore dei controlli e non il controllo uguale.
Steel Brain,

inoltre non porta nulla di nuovo sul tavolo, rispetto a nessuna delle risposte che ci sono state dal ~ 2011.
amenthes,

1

Inserito le risposte migliori in un prototipo per ordinare in base alla chiave.

Array.prototype.alphaSortByKey= function (key) {
    this.sort(function (a, b) {
        if (a[key] < b[key])
            return -1;
        if (a[key] > b[key])
            return 1;
        return 0;
    });
    return this;
};

0

Puoi usare qualcosa di simile per sbarazzarti della distinzione tra maiuscole e minuscole

users.sort(function(a, b){

  //compare two values
  if(a.firstname.toLowerCase() < b.firstname.toLowerCase()) return -1;
  if(a.firstname.toLowerCase() > b.firstname.toLowerCase()) return 1;
  return 0;

})

7
Stessa risposta di quella di Mrchief. Con l'ulteriore svantaggio che toLowerCase viene eseguito quattro volte per confronto anziché due volte.
amenthes,

0

La mia implementazione funziona alla grande nelle versioni ES precedenti:

sortObject = function(data) {
    var keys = Object.keys(data);
    var result = {};

    keys.sort();

    for(var i = 0; i < keys.length; i++) {
        var key = keys[i];

        result[key] = data[key];
    }

    return result;
};

0

Solo per la cronaca, se si desidera avere una funzione di ordinamento denominata, la sintassi è la seguente:

let sortFunction = (a, b) => {
 if(a.firstname < b.firstname) { return -1; }
 if(a.firstname > b.firstname) { return 1; }
 return 0;
})
users.sort(sortFunction)

Si noti che quanto segue NON funziona:

users.sort(sortFunction(a,b))
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.