Ordina l'oggetto JavaScript per chiave


532

Devo ordinare gli oggetti JavaScript per chiave.

Da qui il seguente:

{ 'b' : 'asdsad', 'c' : 'masdas', 'a' : 'dsfdsfsdf' }

Potrebbe diventare:

{ 'a' : 'dsfdsfsdf', 'b' : 'asdsad', 'c' : 'masdas' }

3
possibile duplicato dell'ordinamento di un oggetto JSON in Javascript
abraham,

39
Nel 2011 (quando è stata pubblicata questa domanda), la specifica ECMAScript ha affermato che gli oggetti JavaScript non hanno un ordine intrinseco: l'ordine osservato dipendeva dall'implementazione e quindi non poteva essere invocato. Tuttavia, risulta che tutti i motori JavaScript hanno implementato più o meno la stessa semantica, quindi ora sono stati standardizzati in ES6 . Di conseguenza, molte delle risposte sottostanti erano corrette secondo le specifiche, ma ora sono errate.
Mathias Bynens,

in breve, usa il criterio di ordinamento ordinato quando devi confrontare o eseguire il hash dei risultati: npmjs.com/package/json-stable-stringify
exebook

Dato che gli oggetti sono solo mappe, o dicts a seconda della tua lingua, non c'è motivo per cui potresti farlo. CHE DETTO CHE, IN GENERALE, l'ordine in cui vengono iniettati in una mappa è in realtà l'ordine in cui risiedono quando si stringono. Quindi, se hai creato una nuova mappa e assegnato valori basati su un elenco di chiavi preordinate, ti ritroverai una mappa ordinata basata su chiavi
Fallenreaper,

Si noti che da allora Object.entriese Object.fromEntriessono stati aggiunti a JS, questo può essere ottenuto con un one-liner ben breve:Object.fromEntries(Object.entries(obj).sort())
Mike 'Pomax' Kamermans,

Risposte:


472

Le altre risposte a questa domanda sono obsolete, non corrispondono mai alla realtà dell'implementazione e sono ufficialmente diventate errate ora che le specifiche ES6 / ES2015 sono state pubblicate.


Vedi la sezione sull'ordine di iterazione delle proprietà in Exploring ES6 di Axel Rauschmayer :

Tutti i metodi che ripetono le chiavi delle proprietà lo fanno nello stesso ordine:

  1. Innanzitutto tutti gli indici di array, ordinati numericamente.
  2. Quindi tutte le chiavi di stringa (che non sono indici), nell'ordine in cui sono state create.
  3. Quindi tutti i simboli, nell'ordine in cui sono stati creati.

Quindi sì, gli oggetti JavaScript sono infatti ordinati e l'ordine delle loro chiavi / proprietà può essere modificato.

Ecco come ordinare un oggetto in base alle sue chiavi / proprietà, in ordine alfabetico:

const unordered = {
  'b': 'foo',
  'c': 'bar',
  'a': 'baz'
};

console.log(JSON.stringify(unordered));
// → '{"b":"foo","c":"bar","a":"baz"}'

const ordered = {};
Object.keys(unordered).sort().forEach(function(key) {
  ordered[key] = unordered[key];
});

console.log(JSON.stringify(ordered));
// → '{"a":"baz","b":"foo","c":"bar"}'

Utilizzare varinvece che constper la compatibilità con i motori ES5.


5
Non riesco davvero a vedere una differenza per il tuo codice e la risposta migliore qui a parte l'utilizzo di una tecnica di loop leggermente diversa. Il fatto che gli oggetti possano o meno essere "ordinati" o no sembra essere irrilevante. La risposta a questa domanda è sempre la stessa. Le specifiche pubblicate confermano semplicemente le risposte qui.
Phil,

6
Cordiali saluti, è stato chiarito che l' ordine di enumerazione delle proprietà è ancora indefinito: esdiscuss.org/topic/…
Felix Kling

6
@ Phil_1984_ Questa risposta e la risposta più votata sono molto diverse. La domanda di OP era come ordinare un oggetto letteralmente. La risposta più votata dice che non è possibile, quindi fornisce una soluzione alternativa memorizzando le chiavi ordinate in un array, quindi ripetendo e stampando le coppie di valori chiave dall'array ordinato. Questa risposta afferma che l'ordine dei valori letterali degli oggetti è ora ordinabile e il suo esempio memorizza i valori della chiave ordinata in un valore letterale dell'oggetto, quindi stampa direttamente l'oggetto ordinato. A parte questo, sarebbe bello se il sito collegato esistesse ancora.
cchamberlain,

6
Entrambe le risposte usano semplicemente la funzione Array.sort per ordinare prima i tasti. L'OP chiede di ordinare un "oggetto JavaScript" e utilizza semplicemente JavaScript Object Notation (JSON) per descrivere i 2 oggetti. Questi 2 oggetti sono logicamente identici, il che significa che l'ordinamento è irrilevante. Penso che la risposta migliore lo spieghi molto meglio. Dire "tutte le altre risposte ora sono ufficialmente errate" è troppo estremo per me, soprattutto con un link non funzionante. Penso che il problema sia "questa nuova specifica ES6" sta dando l'illusione che gli oggetti Javascript abbiano un elenco ordinato di chiavi che semplicemente non è vero.
Phil

1
Si prega di aggiungere che questa soluzione non è supportata da una varietà di browser moderni (google "caniuse ES6"). L'utilizzo di queste risposte comporta la presenza di bug difficili da trovare solo in alcuni browser (ad esempio Safari quando Chrome va bene).
Manuel Arwed Schmidt,

244

Gli oggetti JavaScript 1 non sono ordinati. Non ha senso cercare di "ordinarli". Se si desidera scorrere le proprietà di un oggetto, è possibile ordinare le chiavi e quindi recuperare i valori associati:

var myObj = {
    'b': 'asdsadfd',
    'c': 'masdasaf',
    'a': 'dsfdsfsdf'
  },
  keys = [],
  k, i, len;

for (k in myObj) {
  if (myObj.hasOwnProperty(k)) {
    keys.push(k);
  }
}

keys.sort();

len = keys.length;

for (i = 0; i < len; i++) {
  k = keys[i];
  console.log(k + ':' + myObj[k]);
}


Implementazione alternativa usando Object.keysfantasia:

var myObj = {
    'b': 'asdsadfd',
    'c': 'masdasaf',
    'a': 'dsfdsfsdf'
  },
  keys = Object.keys(myObj),
  i, len = keys.length;

keys.sort();

for (i = 0; i < len; i++) {
  k = keys[i];
  console.log(k + ':' + myObj[k]);
}


1 Non essere pedante, ma non esiste un oggetto JSON .


2
@MarcelKorpel Esiste un oggetto JSON. Controlla la sezione 8 della RFC JSON ufficiale: ietf.org/rfc/rfc4627.txt
Paul

8
@Paulpro due cose da notare a proposito di quel RFC: in primo luogo, a questo punto ha 7 anni e il vocabolario cambia nel tempo; secondo, "Questo memo fornisce informazioni per la comunità di Internet. Non specifica uno standard Internet di alcun tipo." Se una determinata sequenza di caratteri rappresenta un oggetto JavaScript letterale o un testo JSON dipende dal contesto / utilizzo. Il termine "oggetto JSON" si confonde e rende ambigua la distinzione in modo dannoso. Liberiamoci della terminologia imprecisa e usiamo il termine più preciso ove possibile. Non vedo alcun motivo per fare diversamente. Le parole contano.
Matt Ball

6
@MattBall IMO JSON Object è un termine molto preciso per una stringa, {"a", 1}proprio come JSON Array è un termine preciso per una stringa come [1]. È utile poter comunicare dicendo cose come il terzo oggetto nel mio array quando si dispone della stringa [{x: 1}, {y: 2}, {z: 3}], quindi preferisco di gran lunga "Questo non è un oggetto JSON" quando si commenta un valore letterale Javascript, piuttosto che "Non esiste cosa come un oggetto JSON ", che causerà più confusione e difficoltà di comunicazione in seguito quando l'OP sta effettivamente lavorando con JSON.
Paul,

3
@Paulpro Non sono d'accordo. {"a", 1}è un oggetto letterale o un testo JSON (aka stringa JSON, se preferisci davvero). Quale dipende dal contesto, il primo se appare testualmente all'interno del codice sorgente JavaScript, il secondo se è una stringa che deve essere passata a un parser JSON per essere utilizzata ulteriormente. Esistono differenze reali tra i due quando si tratta di sintassi consentita, utilizzo corretto e serializzazione.
Matt Ball,

4
Ora che ES6 / ES2015 è stato finalizzato, questa risposta è diventata ufficialmente errata. Vedi la mia risposta per maggiori informazioni.
Mathias Bynens,

172

Molte persone hanno detto che "gli oggetti non possono essere ordinati" , ma dopo ti stanno dando una soluzione che funziona. Paradosso, vero?

Nessuno menziona il motivo per cui quelle soluzioni stanno funzionando. Lo sono, perché nella maggior parte delle implementazioni del browser i valori negli oggetti sono memorizzati nell'ordine in cui sono stati aggiunti. Ecco perché se si crea un nuovo oggetto dall'elenco ordinato di chiavi, viene restituito un risultato previsto.

E penso che potremmo aggiungere un'altra soluzione: il modo funzionale ES5:

function sortObject(obj) {
    return Object.keys(obj).sort().reduce(function (result, key) {
        result[key] = obj[key];
        return result;
    }, {});
}

Versione ES2015 di cui sopra (formattata in "one-liner"):

const sortObject = o => Object.keys(o).sort().reduce((r, k) => (r[k] = o[k], r), {})

Breve spiegazione degli esempi sopra (come richiesto nei commenti):

Object.keysci sta dando un elenco di chiavi nell'oggetto fornito ( objo o), quindi stiamo ordinando quelle usando l'algoritmo di ordinamento predefinito, successivamente .reduceviene usato per riconvertire quell'array in un oggetto, ma questa volta con tutte le chiavi ordinate.


7
@Pointy Questo comportamento è sempre disponibile in tutti i principali browser ed è stato standardizzato in ES6 / ES2015 . Direi che questo è un buon consiglio.
Mathias Bynens,

3
Questo è il modo più semplice e conciso di eseguire l'attività in EcmaScript v5. Un po 'in ritardo alla festa, ma dovrebbe essere la risposta accettata.
Steven de Salas,

2
"Lo sono, perché nella maggior parte delle implementazioni del browser i valori negli oggetti sono memorizzati nell'ordine in cui sono stati aggiunti" Tuttavia, solo per proprietà non numeriche. Si noti inoltre che non esiste ancora alcuna garanzia nell'ordine in cui le proprietà vengono ripetute (ad es. Tramite for...in).
Felix Kling,

2
Gentile da parte tua spiegare perché funziona, ha fatto la lezione per me. Grazie!
ola,

5
La mia linter si è lamentata di quel one-liner (restituendo un incarico), ma questo funziona per me ed è più facile per me leggere:Object.keys(dict).sort().reduce((r, k) => Object.assign(r, { [k]: dict[k] }), {});
aks.

68

Ragazzi sono figurativamente scioccato! Certo, tutte le risposte sono piuttosto vecchie, ma nessuno ha nemmeno menzionato la stabilità nell'ordinamento! Quindi abbi pazienza, farò del mio meglio per rispondere alla domanda stessa e per entrare nei dettagli qui. Quindi mi scuserò ora che sarà molto da leggere.

Dato che è il 2018 userò solo ES6, i Polyfill sono tutti disponibili nei documenti MDN, che collegherò alla parte data.


Rispondi alla domanda:

Se le tue chiavi sono solo numeri, puoi tranquillamente utilizzarlo Object.keys()insieme Array.prototype.reduce()per restituire l'oggetto ordinato:

// Only numbers to show it will be sorted.
const testObj = {
  '2000': 'Articel1',
  '4000': 'Articel2',
  '1000': 'Articel3',
  '3000': 'Articel4',
};

// I'll explain what reduces does after the answer.
console.log(Object.keys(testObj).reduce((accumulator, currentValue) => {
  accumulator[currentValue] = testObj[currentValue];
  return accumulator;
}, {}));

/**
 * expected output:
 * {
 * '1000': 'Articel3',
 * '2000': 'Articel1',
 * '3000': 'Articel4',
 * '4000': 'Articel2' 
 *  } 
 */

// if needed here is the one liner:
console.log(Object.keys(testObj).reduce((a, c) => (a[c] = testObj[c], a), {}));

Tuttavia, se lavori con le stringhe, ti consiglio vivamente di concatenare Array.prototype.sort()tutto ciò:

// String example
const testObj = {
  'a1d78eg8fdg387fg38': 'Articel1',
  'z12989dh89h31d9h39': 'Articel2',
  'f1203391dhj32189h2': 'Articel3',
  'b10939hd83f9032003': 'Articel4',
};
// Chained sort into all of this.
console.log(Object.keys(testObj).sort().reduce((accumulator, currentValue) => {
  accumulator[currentValue] = testObj[currentValue];
  return accumulator;
}, {}));

/**
 * expected output:   
 * { 
 * a1d78eg8fdg387fg38: 'Articel1',
 * b10939hd83f9032003: 'Articel4',
 * f1203391dhj32189h2: 'Articel3',
 * z12989dh89h31d9h39: 'Articel2' 
 * }
 */

// again the one liner:
console.log(Object.keys(testObj).sort().reduce((a, c) => (a[c] = testObj[c], a), {}));

Se qualcuno si chiede cosa riduce:

// Will return Keys of object as an array (sorted if only numbers or single strings like a,b,c).
Object.keys(testObj)

// Chaining reduce to the returned array from Object.keys().
// Array.prototype.reduce() takes one callback 
// (and another param look at the last line) and passes 4 arguments to it: 
// accumulator, currentValue, currentIndex and array
.reduce((accumulator, currentValue) => {

  // setting the accumulator (sorted new object) with the actual property from old (unsorted) object.
  accumulator[currentValue] = testObj[currentValue];

  // returning the newly sorted object for the next element in array.
  return accumulator;

  // the empty object {} ist the initial value for  Array.prototype.reduce().
}, {});

Se necessario, ecco la spiegazione per la copertina:

Object.keys(testObj).reduce(

  // Arrow function as callback parameter.
  (a, c) => 

  // parenthesis return! so we can safe the return and write only (..., a);
  (a[c] = testObj[c], a)

  // initial value for reduce.
  ,{}
);

Perché l'ordinamento è un po 'complicato:

In breve Object.keys()restituirà un array con lo stesso ordine che otteniamo con un normale ciclo:

const object1 = {
  a: 'somestring',
  b: 42,
  c: false
};

console.log(Object.keys(object1));
// expected output: Array ["a", "b", "c"]

Object.keys () restituisce un array i cui elementi sono stringhe corrispondenti alle proprietà enumerabili trovate direttamente sull'oggetto. L'ordinamento delle proprietà è uguale a quello fornito eseguendo il ciclo manualmente sulle proprietà dell'oggetto.

Sidenote: è possibile utilizzare anche Object.keys()su array, tenere presente che l'indice verrà restituito:

// simple array
const arr = ['a', 'b', 'c'];
console.log(Object.keys(arr)); // console: ['0', '1', '2']

Ma non è così facile come mostrato da quegli esempi, gli oggetti del mondo reale possono contenere numeri e caratteri alfabetici o persino simboli (per favore non farlo).

Ecco un esempio con tutti in un oggetto:

// This is just to show what happens, please don't use symbols in keys.
const testObj = {
  '1asc': '4444',
  1000: 'a',
  b: '1231',
  '#01010101010': 'asd',
  2: 'c'
};

console.log(Object.keys(testObj));
// output: [ '2', '1000', '1asc', 'b', '#01010101010' ]

Ora se usiamo Array.prototype.sort()sull'array sopra l'output cambia:

console.log(Object.keys(testObj).sort());
// output: [ '#01010101010', '1000', '1asc', '2', 'b' ]

Ecco una citazione dai documenti:

Il metodo sort () ordina gli elementi di un array sul posto e restituisce l'array. L'ordinamento non è necessariamente stabile. L'ordinamento predefinito è in base ai punti di codice Unicode stringa.

La complessità temporale e spaziale dell'ordinamento non può essere garantita in quanto dipende dall'implementazione.

Devi assicurarti che uno di essi restituisca l'output desiderato per te. Negli esempi di vita reale le persone tendono a mescolare le cose soprattutto se si utilizzano insieme input di informazioni diverse come API e database.


Quindi qual è il grosso problema?

Bene, ci sono due articoli che ogni programmatore dovrebbe capire:

Algoritmo sul posto :

Nell'informatica, un algoritmo sul posto è un algoritmo che trasforma l'input senza alcuna struttura di dati ausiliaria. Tuttavia, è consentita una piccola quantità di spazio di archiviazione aggiuntivo per le variabili ausiliarie. L'input viene in genere sovrascritto dall'output durante l'esecuzione dell'algoritmo. L'algoritmo sul posto aggiorna la sequenza di input solo attraverso la sostituzione o lo scambio di elementi. Un algoritmo che non è sul posto è talvolta chiamato non sul posto o fuori posto.

Quindi in pratica il nostro vecchio array verrà sovrascritto! Questo è importante se si desidera mantenere il vecchio array per altri motivi. Quindi tienilo a mente.

Algoritmo di ordinamento

Gli algoritmi di ordinamento stabili ordinano gli elementi identici nello stesso ordine in cui compaiono nell'input. Quando si ordinano alcuni tipi di dati, solo una parte dei dati viene esaminata quando si determina l'ordinamento. Ad esempio, nell'esempio di ordinamento delle carte a destra, le carte vengono ordinate in base al loro valore e il loro seme viene ignorato. Ciò consente la possibilità di più diverse versioni ordinate correttamente dell'elenco originale. Gli algoritmi di ordinamento stabile scelgono uno di questi, secondo la seguente regola: se due elementi si confrontano come uguali, come le due 5 carte, il loro ordine relativo verrà preservato, in modo che se uno venisse prima dell'altro nell'input, anche venire prima dell'altro nell'output.

inserisci qui la descrizione dell'immagine

Un esempio di ordinamento stabile sulle carte da gioco. Quando le carte sono ordinate per rango con un ordinamento stabile, i due 5 devono rimanere nello stesso ordine nell'output ordinato in cui erano originariamente. Quando sono ordinati con un ordinamento non stabile, i 5 possono finire nel contrario ordine nell'output ordinato.

Ciò dimostra che l'ordinamento è corretto ma è cambiato. Quindi, nel mondo reale, anche se l'ordinamento è corretto, dobbiamo assicurarci di ottenere ciò che ci aspettiamo! Questo è molto importante tenere presente anche questo. Per ulteriori esempi JavaScript, consultare Array.prototype.sort () - docs: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort


3
Lanciando rock, grazie per questa incredibile risposta. Uno dei migliori che abbia mai visto su SO. Saluti.
Gavin,

Se solo potessi fornire un metodo pazzesco da usare alla fine. Ottima risposta però!
mmm

@momomo il problema è che, a seconda di cosa ti aspetti dall'ordinamento, non esiste un metodo giusto. Tuttavia si può semplicemente utilizzare questo pezzo di codice da mia risposta: Object.keys(testObj).sort().reduce((a, c) => (a[c] = testObj[c], a), {}).
Megajin,

La stabilità del tipo non è applicabile a questa domanda: stiamo ordinando per chiave oggetto e la chiave è unica. (Per estendere l'esempio della tua carta: non possono mai esserci due 5 nel mazzo, anche se hanno semi diversi.)
Darren Cook,

@Darren: buona domanda! Hai ragione, non ci sarà mai la stessa chiave in un oggetto. Tuttavia, la stabilità è più complessa della sola unicità di una chiave. Il più delle volte un array è incluso negli oggetti di ordinamento. Ed è allora che tutto può diventare instabile. Immagina un gioco di carte con 5 giocatori. Ogni mano è rappresentata da un array (per mantenere l'ordinamento di una singola mano) e le carte come oggetti. Se la tua carta è simile a questa {5: 'hearts'}o {5: 'spades'}inizi a ordinare l'array, diventerà potenzialmente instabile in giochi come il ramino. Per non parlare di lingue diverse.
Megajin,

29

Questo funziona per me

/**
 * Return an Object sorted by it's Key
 */
var sortObjectByKey = function(obj){
    var keys = [];
    var sorted_obj = {};

    for(var key in obj){
        if(obj.hasOwnProperty(key)){
            keys.push(key);
        }
    }

    // sort keys
    keys.sort();

    // create new array based on Sorted Keys
    jQuery.each(keys, function(i, key){
        sorted_obj[key] = obj[key];
    });

    return sorted_obj;
};

10
Questa è in realtà la risposta corretta alla domanda in corso. Per una versione semplificata con Underscore, consultare: jsfiddle.net/wPjaQ/1
radicand

6
@radicand No questa risposta non è corretta. Restituisce un nuovo oggetto, che non ha alcun ordine.
Paul,

3
@radicand Neanche in pratica. Non esiste un ordine sulle chiavi degli oggetti, quindi come si può dire che in pratica questo ti dà un oggetto in ordine? Ti restituisce solo una copia superficiale dell'oggetto che passi.
Paul,

9
Questo è super sbagliato. Potrebbe funzionare per ora, ma si interromperà in un browser Web diverso o caricherà pagine diverse nello stesso browser. I browser possono randomizzare le chiavi degli oggetti per motivi di sicurezza o, mentre si riempie un oggetto, inserirà i valori in diversi secchi di memoria a seconda delle chiavi, che restituiranno un ordine diverso. Se questo funziona, è solo una fortuna per te.
Yobert,

11
Ha anche un uso inutile di jQuery.
RobG

25

È il 2019 e abbiamo un modo per risolverlo nel 2019 :)

Object.fromEntries(Object.entries({b: 3, a:8, c:1}).sort())

2
Come ordinare gli oggetti nidificati per chiave?
a2441918

@ a2441918 Come si farebbe con la funzione sort (). Dai un'occhiata: developer.mozilla.org/de/docs/Web/JavaScript/Reference/… Object.fromEntries (Object.entries ({b: 3, a: 8, c: 1}). Sort ((k, j ) => k - j))
user2912903

Per gli utenti di TypeScript questo non è ancora disponibile per noi, consultare: github.com/microsoft/TypeScript/issues/30933
tsujp

Nice one-liner, ma come ordinare le chiavi in ​​modo insensibile alle maiuscole?
theMaxx

1
@theMaxx Usa una funzione personalizzata per ordinare, qualcosa del tipo: `` `Object.fromEntries (Object.entries ({b: 3, a: 8, c: 1}). sort (([key1, val1], [key2, val2]) => key1.toLowerCase (). localeCompare (key2.toLowerCase ()))) ``
Ben

22

ecco la 1 linea

var data = { zIndex:99,
             name:'sravan',
             age:25, 
             position:'architect',
             amount:'100k',
             manager:'mammu' };

console.log(Object.entries(data).sort().reduce( (o,[k,v]) => (o[k]=v,o), {} ));


Che diamine è questa pazza sintassi? (o[k] = v, o). Perché funziona anche questo, dove posso trovare documenti a riguardo? Restituisce ovviamente il parametro più a destra, ma perché?
ntaso,

1
@ntaso qui
James,

prima la funzione breve fa o[k]uguagliare ve poi ritornao
Tahsin Turkoz,

19

Questa è una vecchia domanda, ma prendendo spunto dalla risposta di Mathias Bynens, ho realizzato una versione breve per ordinare l' oggetto corrente , senza troppe spese generali.

    Object.keys(unordered).sort().forEach(function(key) {
        var value = unordered[key];
        delete unordered[key];
        unordered[key] = value;
    });

dopo l'esecuzione del codice, l'oggetto "non ordinato" stesso avrà le chiavi ordinate alfabeticamente.


17

Usando lodash questo funzionerà:

some_map = { 'b' : 'asdsad', 'c' : 'masdas', 'a' : 'dsfdsfsdf' }

// perform a function in order of ascending key
_(some_map).keys().sort().each(function (key) {
  var value = some_map[key];
  // do something
});

// or alternatively to build a sorted list
sorted_list = _(some_map).keys().sort().map(function (key) {
  var value = some_map[key];
  // return something that shall become an item in the sorted list
}).value();

Solo spunti di riflessione.


15

Supponiamo che possa essere utile nel debugger di VisualStudio che mostra le proprietà degli oggetti non ordinate.

(function(s){var t={};Object.keys(s).sort().forEach(function(k){t[k]=s[k]});return t})({b:2,a:1,c:3})

So Great Thanks a loooot
Mugiwara

Bello! Grazie per questa soluzione concisa.
Con Antonakos,

9

Versione di sottolineatura :

function order(unordered)
{
return _.object(_.sortBy(_.pairs(unordered),function(o){return o[0]}));
}

Se non ti fidi del tuo browser per mantenere l'ordine delle chiavi, ti consiglio vivamente di fare affidamento su un array ordinato di array accoppiati valore-chiave.

_.sortBy(_.pairs(c),function(o){return o[0]})

Meglio:_.object(_.sortBy(_.pairs(unordered), _.first))
Afanasii Kurakin il

8
function sortObjectKeys(obj){
    return Object.keys(obj).sort().reduce((acc,key)=>{
        acc[key]=obj[key];
        return acc;
    },{});
}

sortObjectKeys({
    telephone: '069911234124',
    name: 'Lola',
    access: true,
});

Forse aggiungere qualche spiegazione del tuo codice è meglio.
Aristotele,

1
Ottiene le chiavi dell'oggetto, quindi è una matrice di stringhe, le ordino () e siccome è una matrice di stringhe (chiavi) le riduco (con riduci () di js Array). L'acc è inizialmente un oggetto vuoto {} (ultimo argomento del riduttore) e il riduttore (callback) assegna all'oggetto vuoto i valori dell'oggetto sorgente con la sequenza di tasti ordinata.
user3286817

8

Forse una forma un po 'più elegante:

 /**
     * Sorts a key-value object by key, maintaining key to data correlations.
     * @param {Object} src  key-value object
     * @returns {Object}
     */
var ksort = function ( src ) {
      var keys = Object.keys( src ),
          target = {};
      keys.sort();
      keys.forEach(function ( key ) {
        target[ key ] = src[ key ];
      });
      return target;
    };


// Usage
console.log(ksort({
  a:1,
  c:3,
  b:2  
}));

PS e lo stesso con la sintassi ES6 +:

function ksort( src ) {
  const keys = Object.keys( src );
  keys.sort();
  return keys.reduce(( target, key ) => {
        target[ key ] = src[ key ];
        return target;
  }, {});
};

non è niente. stai ancora restituendo un oggetto. non puoi garantire che gli oggetti nel tuo bersaglio abbiano effettivamente un ordine. è necessario restituire un array. jeeezus.
mmm

l'unica cosa che stai facendo qui è assicurarti che sia un set, in modo non ottimale.
mmm

7

ordinamento ricorsivo, per oggetti nidificati e array

function sortObjectKeys(obj){
    return Object.keys(obj).sort().reduce((acc,key)=>{
        if (Array.isArray(obj[key])){
            acc[key]=obj[key].map(sortObjectKeys);
        }
        if (typeof obj[key] === 'object'){
            acc[key]=sortObjectKeys(obj[key]);
        }
        else{
            acc[key]=obj[key];
        }
        return acc;
    },{});
}

// test it
sortObjectKeys({
    telephone: '069911234124',
    name: 'Lola',
    access: true,
    cars: [
        {name: 'Family', brand: 'Volvo', cc:1600},
        {
            name: 'City', brand: 'VW', cc:1200, 
            interior: {
                wheel: 'plastic',
                radio: 'blaupunkt'
            }
        },
        {
            cc:2600, name: 'Killer', brand: 'Plymouth',
            interior: {
                wheel: 'wooden',
                radio: 'earache!'
            }
        },
    ]
});

Penso che tu abbia bisogno di un elsedentro - potrebbe essere vero per entrambi Array.isArray(obj[key])e pertypeof obj[key] === 'object'
jononomo il

Quando si dispone di una matrice di primitive, la funzione trasforma le primitive (stringa / numero) in oggetti vuoti. Per catturare questo ho aggiunto il seguente proprio all'inizio della funzione: function sortObjectKeys(obj){: if(typeof obj != 'object'){ /* it is a primitive: number/string (in an array) */ return obj; }. Per robustezza ho anche aggiunto all'inizio:if(obj == null || obj == undefined){ return obj; }
stato il

4

Come già accennato, gli oggetti non sono ordinati.

Però...

Potresti trovare utile questo linguaggio:

var o = { 'b' : 'asdsad', 'c' : 'masdas', 'a' : 'dsfdsfsdf' };

var kv = [];

for (var k in o) {
  kv.push([k, o[k]]);
}

kv.sort()

Puoi quindi scorrere attraverso kv e fare quello che desideri.

> kv.sort()
[ [ 'a', 'dsfdsfsdf' ],
  [ 'b', 'asdsad' ],
  [ 'c', 'masdas' ] ]


4

Ecco una versione pulita basata su lodash che funziona con oggetti nidificati

/**
 * Sort of the keys of an object alphabetically
 */
const sortKeys = function(obj) {
  if(_.isArray(obj)) {
    return obj.map(sortKeys);
  }
  if(_.isObject(obj)) {
    return _.fromPairs(_.keys(obj).sort().map(key => [key, sortKeys(obj[key])]));
  }
  return obj;
};

Sarebbe anche più pulito se lodash avesse un toObject()metodo ...


3

Basta usare lodash per decomprimere la mappa e ordinare Per primo valore di coppia e zip di nuovo restituirà la chiave ordinata.

Se si desidera il valore di ordinamento, modificare l'indice di coppia su 1 anziché su 0

var o = { 'b' : 'asdsad', 'c' : 'masdas', 'a' : 'dsfdsfsdf' };
console.log(_(o).toPairs().sortBy(0).fromPairs().value())

inserisci qui la descrizione dell'immagine


Utilizza il link di modifica per spiegare come funziona questo codice e non limitarti a fornire il codice, poiché è più probabile che una spiegazione aiuti i lettori futuri. Vedi anche Come rispondere . fonte
Jed Fox,

3

Ordina le chiavi in ​​modo ricorsivo preservando i riferimenti.

function sortKeys(o){
    if(o && o.constructor === Array)
        o.forEach(i=>sortKeys(i));
    else if(o && o.constructor === Object)
        Object.entries(o).sort((a,b)=>a[0]>b[0]?1:-1).forEach(e=>{
            sortKeys(e[1]);
            delete o[e[0]];
            o[e[0]] = e[1];
        });
}

Esempio:

let x = {d:3, c:{g:20, a:[3,2,{s:200, a:100}]}, a:1};
let y = x.c;
let z = x.c.a[2];
sortKeys(x);
console.log(x); // {a: 1, c: {a: [3, 2, {a: 1, s: 2}], g: 2}, d: 3}
console.log(y); // {a: [3, 2, {a: 100, s: 200}}, g: 20}
console.log(z); // {a: 100, s: 200}

Bel frammento! Qual è lo scopo di delete o[e[0]];lì? Non possiamo semplicemente assegnare?
Boyang,

Sembra che solo le nuove assegnazioni a chiavi inesistenti aggiungano la chiave alla fine. Se si elimina commenta, le chiavi non verranno ordinate, almeno non in Chrome.
Brunettdan,

questo ha senso. Grazie! In ogni caso, questa è una specie di causa persa perché le chiavi dell'oggetto js non hanno sequenza, secondo le specifiche. Stiamo solo sfruttando i dettagli impl della funzione obj e log
Boyang,

Sì, uso la mappa quando l'ordine delle chiavi è importante: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
brunettdan,

3
Object.keys(unordered).sort().reduce(
    (acc,curr) => ({...acc, [curr]:unordered[curr]})
    , {}
)

3

Questa è una soluzione leggera a tutto ciò di cui ho bisogno per l'ordinamento JSON.

function sortObj(obj) {
    if (typeof obj !== "object" || obj === null)
        return obj;

    if (Array.isArray(obj))
        return obj.map((e) => sortObj(e)).sort();

    return Object.keys(obj).sort().reduce((sorted, k) => {
        sorted[k] = sortObj(obj[k]);
        return sorted;
    }, {});
}

2

Utilizzare questo codice se si hanno oggetti nidificati o se si dispone di oggetti nidificati obj.

var sortObjectByKey = function(obj){
    var keys = [];
    var sorted_obj = {};
    for(var key in obj){
        if(obj.hasOwnProperty(key)){
            keys.push(key);
        }
    }
    // sort keys
    keys.sort();

    // create new array based on Sorted Keys
    jQuery.each(keys, function(i, key){
        var val = obj[key];
        if(val instanceof Array){
            //do for loop;
            var arr = [];
            jQuery.each(val,function(){
                arr.push(sortObjectByKey(this));
            }); 
            val = arr;

        }else if(val instanceof Object){
            val = sortObjectByKey(val)
        }
        sorted_obj[key] = val;
    });
    return sorted_obj;
};

5
L'autore non afferma di usare jQuery, né la domanda è taggata jQuery. Sarebbe bello se aggiungi una soluzione in javascript puro.
rusmus,

Grazie @Phani questo è esattamente ciò di cui avevo bisogno
Will Sheppard

2

Soluzione:

function getSortedObject(object) {
  var sortedObject = {};

  var keys = Object.keys(object);
  keys.sort();

  for (var i = 0, size = keys.length; i < size; i++) {
    key = keys[i];
    value = object[key];
    sortedObject[key] = value;
  }

  return sortedObject;
}

// Test run
getSortedObject({d: 4, a: 1, b: 2, c: 3});

Spiegazione:

Molti runtime JavaScript memorizzano i valori all'interno di un oggetto nell'ordine in cui vengono aggiunti.

Per ordinare le proprietà di un oggetto in base alle loro chiavi, puoi utilizzare la funzione Object.keys che restituirà una matrice di chiavi. L'array di chiavi può quindi essere ordinato in base a Array.prototype.sort () metodo che ordina gli elementi di un array in atto (non è necessario assegnarli a una nuova variabile).

Una volta che le chiavi sono state ordinate, puoi iniziare a usarle una per una per accedere al contenuto del vecchio oggetto per riempire un nuovo oggetto (che ora è ordinato).

Di seguito è riportato un esempio della procedura (puoi testarla nei browser di destinazione):

/**
 * Returns a copy of an object, which is ordered by the keys of the original object.
 *
 * @param {Object} object - The original object.
 * @returns {Object} Copy of the original object sorted by keys.
 */
function getSortedObject(object) {
  // New object which will be returned with sorted keys
  var sortedObject = {};

  // Get array of keys from the old/current object
  var keys = Object.keys(object);
  // Sort keys (in place)
  keys.sort();

  // Use sorted keys to copy values from old object to the new one
  for (var i = 0, size = keys.length; i < size; i++) {
    key = keys[i];
    value = object[key];
    sortedObject[key] = value;
  }

  // Return the new object
  return sortedObject;
}

/**
 * Test run
 */
var unsortedObject = {
  d: 4,
  a: 1,
  b: 2,
  c: 3
};

var sortedObject = getSortedObject(unsortedObject);

for (var key in sortedObject) {
  var text = "Key: " + key + ", Value: " + sortedObject[key];
  var paragraph = document.createElement('p');
  paragraph.textContent = text;
  document.body.appendChild(paragraph);
}

Nota: Object.keys è un metodo ECMAScript 5.1 ma qui è un polyfill per i browser più vecchi:

if (!Object.keys) {
  Object.keys = function (object) {
    var key = [];
    var property = undefined;
    for (property in object) {
      if (Object.prototype.hasOwnProperty.call(object, property)) {
        key.push(property);
      }
    }
    return key;
  };
}

2

Ho trasferito alcuni enum Java su oggetti javascript.

Questi oggetti mi hanno restituito array corretti. se le chiavi dell'oggetto sono di tipo misto (stringa, int, carattere), c'è un problema.

Types:

var TypeA = {
    "-1": "Any",
    "2": "2L",
    "100": "100L",
    "200": "200L",
    "1000": "1000L"
};

var TypeB = {
    "U": "Any",
    "W": "1L",
    "V": "2L",
    "A": "100L",
    "Z": "200L",
    "K": "1000L"
};


Sorted Keys(output):

Key list of TypeA -> ["-1", "2", "100", "200", "1000"]

Key list of TypeB -> ["U", "W", "V", "A", "Z", "K"]

2

Frammento semplice e leggibile, usando lodash.

Devi inserire la chiave tra virgolette solo quando chiami sortBy. Non deve essere tra virgolette nei dati stessi.

_.sortBy(myObj, "key")

Inoltre, il secondo parametro da mappare è errato. Dovrebbe essere una funzione, ma usare pluck è più semplice.

_.map( _.sortBy(myObj, "key") , "value");

2

C'è un grande progetto di @sindresorhus chiamato sort-keys che funziona alla grande.

Puoi controllare il suo codice sorgente qui:

https://github.com/sindresorhus/sort-keys

Oppure puoi usarlo con npm:

$ npm install --save sort-keys

Qui ci sono anche esempi di codice dal suo readme

const sortKeys = require('sort-keys');

sortKeys({c: 0, a: 0, b: 0});
//=> {a: 0, b: 0, c: 0}

sortKeys({b: {b: 0, a: 0}, a: 0}, {deep: true});
//=> {a: 0, b: {a: 0, b: 0}}

sortKeys({c: 0, a: 0, b: 0}, {
    compare: (a, b) => -a.localeCompare(b)
});
//=> {c: 0, b: 0, a: 0}

1

Risposta JavaScript pura per ordinare un oggetto. Questa è l'unica risposta che conosco che gestirà i numeri negativi. Questa funzione serve per ordinare gli oggetti numerici.

Input obj = {1000: {}, -1200: {}, 10000: {}, 200: {}};

function osort(obj) {
var keys = Object.keys(obj);
var len = keys.length;
var rObj = [];
var rK = [];
var t = Object.keys(obj).length;
while(t > rK.length) {
    var l = null;
    for(var x in keys) {
        if(l && parseInt(keys[x]) < parseInt(l)) {
            l = keys[x];
            k = x;
        }
        if(!l) { // Find Lowest
            var l = keys[x];
            var k = x;
        }
    }
    delete keys[k];
    rK.push(l);
}

for (var i = 0; i < len; i++) {

    k = rK[i];
    rObj.push(obj[k]);
}
return rObj;
}

L'output sarà un oggetto ordinato da quei numeri con nuove chiavi a partire da 0.


1

Giusto per semplificarlo e rendere più chiara la risposta di Matt Ball

//your object
var myObj = {
    b : 'asdsadfd',
    c : 'masdasaf',
    a : 'dsfdsfsdf'
  };

//fixed code
var keys = [];
for (var k in myObj) {
  if (myObj.hasOwnProperty(k)) {
    keys.push(k);
  }
}
keys.sort();
for (var i = 0; i < keys.length; i++) {
  k = keys[i];
  alert(k + ':' + myObj[k]);
}


1

Non sono sicuro se questo risponde alla domanda, ma questo è quello di cui avevo bisogno.

Maps.iterate.sorted = function (o, callback) {
    var keys = Object.keys(o), sorted = keys.sort(), k; 
    if ( callback ) {
            var i = -1;
            while( ++i < sorted.length ) {
                    callback(k = sorted[i], o[k] );
            }
    }

    return sorted;
}

Chiamato come:

Maps.iterate.sorted({c:1, b:2, a:100}, function(k, v) { ... } ) 

1

L'unica linea:

Object.entries(unordered)
  .sort(([keyA], [keyB]) => keyA > keyB)
  .reduce((obj, [key,value]) => Object.assign(obj, {[key]: value}), {})

1

il modo migliore per farlo è

 const object =  Object.keys(o).sort().reduce((r, k) => (r[k] = o[k], r), {})

 //else if its in reverse just do 

 const object = Object.keys(0).reverse ()

Puoi prima convertire il tuo oggetto simile a un array quasi in un array reale, quindi utilizzare .reverse ():

Object.assign([], {1:'banana', 2:'apple', 
3:'orange'}).reverse();
// [ "orange", "apple", "banana", <1 empty slot> ]

Lo slot vuoto alla fine se causa perché il tuo primo indice è 1 invece di 0. Puoi rimuovere lo slot vuoto con .length-- o .pop ().

In alternativa, se si desidera prendere in prestito .reverse e chiamarlo sullo stesso oggetto, deve essere un oggetto simile ad un array completo. Cioè, ha bisogno di una proprietà lunghezza:

Array.prototype.reverse.call({1:'banana', 2:'apple', 
3:'orange', length:4});
// {0:"orange", 1:"apple", 3:"banana", length:4}

Nota che restituirà lo stesso oggetto oggetto simile ad un array completo, quindi non sarà un array reale. È quindi possibile utilizzare Elimina per rimuovere la proprietà length.

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.