Sortieren Sie das JavaScript-Objekt nach Schlüssel

532

Ich muss JavaScript-Objekte nach Schlüssel sortieren.

Daher folgendes:

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

Würde werden:

{ 'a' : 'dsfdsfsdf', 'b' : 'asdsad', 'c' : 'masdas' }
vdh_ant
quelle
3
Mögliches Duplikat des Sortierens eines JSON-Objekts in Javascript
Abraham
39
Im Jahr 2011 (als diese Frage gestellt wurde) wurde in der ECMAScript-Spezifikation angegeben, dass JavaScript-Objekte keine inhärente Reihenfolge haben - die beobachtete Reihenfolge war implementierungsabhängig und konnte daher nicht als zuverlässig angesehen werden. Es stellt sich jedoch heraus, dass alle JavaScript-Engines mehr oder weniger dieselbe Semantik implementiert haben, sodass diese jetzt in ES6 standardisiert wurden . Infolgedessen waren viele der folgenden Antworten gemäß der Spezifikation korrekt, sind jetzt jedoch falsch.
Mathias Bynens
Kurz gesagt, verwenden Sie sortiertes Stringify, wenn Sie die Ergebnisse vergleichen oder hashen müssen: npmjs.com/package/json-stable-stringify
exebook
Angesichts der Tatsache, dass Objekte je nach Sprache nur Karten oder Diktate sind, gibt es kaum einen Grund, warum Sie dies tun würden. DAS WIRD GESAGT, Im Allgemeinen ist die Reihenfolge, in der sie in eine Karte eingefügt werden, tatsächlich die Reihenfolge, in der sie sich beim Stringifizieren befinden. Wenn Sie also eine neue Karte erstellt und Werte basierend auf einer vorsortierten Schlüsselliste zugewiesen haben, finden Sie eine geordnete Karte basierend auf Schlüsseln
Fallenreaper
Beachten Sie, dass seitdem Object.entriesund Object.fromEntriesJS hinzugefügt wurden, kann dies mit einem schön kurze Einzeiler erreicht werden:Object.fromEntries(Object.entries(obj).sort())
Mike ‚Pomax‘ Kamermans

Antworten:

471

Die anderen Antworten auf diese Frage sind veraltet, entsprechen nie der Implementierungsrealität und sind nach Veröffentlichung der ES6 / ES2015-Spezifikation offiziell falsch geworden.


Weitere Informationen finden Sie im Abschnitt zur Reihenfolge der Eigenschaftsiteration in Exploring ES6 von Axel Rauschmayer :

Alle Methoden, die über Eigenschaftsschlüssel iterieren, tun dies in derselben Reihenfolge:

  1. Zunächst alle Array-Indizes, numerisch sortiert.
  2. Dann alle Zeichenfolgenschlüssel (die keine Indizes sind) in der Reihenfolge, in der sie erstellt wurden.
  3. Dann alle Symbole in der Reihenfolge, in der sie erstellt wurden.

Ja, JavaScript-Objekte sind tatsächlich geordnet, und die Reihenfolge ihrer Schlüssel / Eigenschaften kann geändert werden.

So können Sie ein Objekt alphabetisch nach seinen Schlüsseln / Eigenschaften sortieren:

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"}'

Verwenden Sie varstatt constfür die Kompatibilität mit ES5-Motoren.

Mathias Bynens
quelle
5
Ich kann wirklich keinen Unterschied zu Ihrem Code und der Top-Antwort hier sehen, abgesehen von einer etwas anderen Schleifentechnik. Ob die Objekte als "geordnet" bezeichnet werden können oder nicht, scheint irrelevant zu sein. Die Antwort auf diese Frage ist immer noch dieselbe. Die veröffentlichte Spezifikation bestätigt lediglich die Antworten hier.
Phil
6
Zu Ihrer Information , es wurde klargestellt, dass die Aufzählungsreihenfolge der Eigenschaften noch nicht definiert ist: esdiscuss.org/topic/…
Felix Kling
6
@ Phil_1984_ Diese Antwort und die Antwort mit der höchsten Bewertung sind sehr unterschiedlich. Die Frage von OP war, wie ein Objektliteral sortiert werden kann. Die Antwort mit der höchsten Bewertung besagt, dass dies nicht möglich ist. Anschließend wird eine Problemumgehung durchgeführt, indem sortierte Schlüssel in einem Array gespeichert und anschließend Schlüsselwertpaare aus dem sortierten Array iteriert und gedruckt werden. Diese Antwort behauptet, dass die Reihenfolge der Objektliterale jetzt sortierbar ist und sein Beispiel die sortierten Schlüsselwerte in einem Objektliteral speichert und dann das sortierte Objekt direkt druckt. Nebenbei bemerkt wäre es schön, wenn die verlinkte Seite noch existieren würde.
Cchamberlain
6
Beide Antworten verwenden einfach die Array.sort-Funktion, um zuerst die Schlüssel zu sortieren. Das OP fordert zum Sortieren eines "JavaScript-Objekts" auf und verwendet lediglich die JavaScript-Objektnotation (JSON), um die beiden Objekte zu beschreiben. Diese beiden Objekte sind logisch identisch, was bedeutet, dass die Sortierung irrelevant ist. Ich denke, die beste Antwort erklärt dies viel besser. Zu sagen, "alle anderen Antworten sind jetzt offiziell falsch", ist zu extrem für mich, insbesondere bei einem defekten Link. Ich denke, das Problem ist, dass "diese neue ES6-Spezifikation" die Illusion vermittelt, dass Javascript-Objekte eine geordnete Liste von Schlüsseln haben, was einfach nicht stimmt.
Phil
1
Bitte fügen Sie hinzu, dass diese Lösung von einer Vielzahl moderner Browser (Google "caniuse ES6") nicht unterstützt wird. Wenn Sie diese Antworten verwenden, besteht die Gefahr, dass nur in bestimmten Browsern schwer zu findende Fehler auftreten (z. B. Safari, wenn Chrome in Ordnung ist).
Manuel Arwed Schmidt
244

JavaScript-Objekte 1 sind nicht geordnet. Es ist sinnlos zu versuchen, sie zu "sortieren". Wenn Sie die Eigenschaften eines Objekts durchlaufen möchten, können Sie die Schlüssel sortieren und dann die zugehörigen Werte abrufen:

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


Alternative Implementierung mit Object.keysPhantasie:

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 Um nicht pedantisch zu sein, aber es gibt kein JSON-Objekt .

Matt Ball
quelle
2
@MarcelKorpel Es gibt so etwas wie ein JSON-Objekt. Überprüfen Sie Abschnitt 8 des offiziellen JSON RFC: ietf.org/rfc/rfc4627.txt
Paul
8
@Paulpro zwei Dinge, die bei diesem RFC zu beachten sind: Erstens ist es zu diesem Zeitpunkt 7 Jahre alt und der Wortschatz ändert sich im Laufe der Zeit. Zweitens: "Dieses Memo enthält Informationen für die Internet-Community. Es gibt keinerlei Internet-Standard an." Ob eine bestimmte Zeichenfolge ein JavaScript-Objektliteral oder einen JSON-Text darstellt, hängt vom Kontext / der Verwendung ab. Der Begriff "JSON-Objekt" verschmilzt und macht die Unterscheidung in nachteiliger Weise mehrdeutig. Lassen Sie uns die ungenaue Terminologie loswerden und, wo möglich, den genaueren Begriff verwenden. Ich sehe keinen Grund, etwas anderes zu tun. Worte sind wichtig.
Matt Ball
6
@MattBall IMO JSON-Objekt ist ein sehr präziser Begriff für eine Zeichenfolge wie {"a", 1}JSON Array ist ein präziser Begriff für eine Zeichenfolge wie [1]. Es ist nützlich, in der Lage zu sein, zu kommunizieren, indem Sie Dinge wie das dritte Objekt in meinem Array sagen, wenn Sie die Zeichenfolge haben. [{x: 1}, {y: 2}, {z: 3}]Daher bevorzuge ich "Das ist kein JSON-Objekt", wenn ich ein Javascript-Literal kommentiere, anstatt "Es gibt kein solches." Ding als JSON-Objekt ", was später, wenn das OP tatsächlich mit JSON arbeitet, zu mehr Verwirrung und Kommunikationsschwierigkeiten führen wird.
Paul
3
@ Paulpro Ich muss nicht zustimmen. {"a", 1}ist entweder ein Objektliteral oder ein JSON-Text (auch bekannt als JSON-Zeichenfolge, wenn Sie es wirklich bevorzugen). Was es ist, hängt vom Kontext ab. Ersteres, wenn es wörtlich im JavaScript-Quellcode erscheint, letzteres, wenn es sich um eine Zeichenfolge handelt, die an einen JSON-Parser übergeben werden muss, um weiter verwendet zu werden. Es gibt echte Unterschiede zwischen den beiden, wenn es um zulässige Syntax, korrekte Verwendung und Serialisierung geht.
Matt Ball
4
Nachdem ES6 / ES2015 fertiggestellt ist, ist diese Antwort offiziell falsch geworden. Siehe meine Antwort für weitere Informationen.
Mathias Bynens
172

Viele Leute haben erwähnt, dass "Objekte nicht sortiert werden können" , aber danach geben sie Ihnen eine Lösung, die funktioniert. Paradox, nicht wahr?

Niemand erwähnt, warum diese Lösungen funktionieren. Dies ist der Fall, da in den meisten Implementierungen des Browsers Werte in Objekten in der Reihenfolge gespeichert werden, in der sie hinzugefügt wurden. Wenn Sie ein neues Objekt aus einer sortierten Liste von Schlüsseln erstellen, wird daher ein erwartetes Ergebnis zurückgegeben.

Und ich denke, wir könnten noch eine Lösung hinzufügen - ES5-Funktionsweise:

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

ES2015-Version von oben (formatiert als "Einzeiler"):

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

Kurze Erklärung der obigen Beispiele (wie in den Kommentaren gefragt):

Object.keysgibt uns eine Liste der Schlüssel in dem bereitgestellten Objekt ( objoder o), dann sortieren wir diese mit dem Standardsortieralgorithmus. Als nächstes .reducewird dieses Array wieder in ein Objekt konvertiert, diesmal jedoch mit allen Schlüsseln sortiert.

Code Name-
quelle
7
@Pointy Dieses Verhalten war immer in allen gängigen Browsern verfügbar und wurde in ES6 / ES2015 standardisiert . Ich würde sagen, das ist ein guter Rat.
Mathias Bynens
3
Dies ist die einfachste und prägnanteste Methode zum Ausführen von Aufgaben in EcmaScript v5. Ein bisschen spät zur Party, sollte aber die akzeptierte Antwort sein.
Steven de Salas
2
"Sie sind es, weil in den meisten Implementierungen des Browsers Werte in Objekten in der Reihenfolge gespeichert werden, in der sie hinzugefügt wurden." Nur für nicht numerische Eigenschaften. Beachten Sie auch, dass es immer noch keine Garantie gibt, in welcher Reihenfolge die Eigenschaften durchlaufen werden (z for...in. B. via ).
Felix Kling
2
Schön, dass Sie mir erklären, warum es funktioniert. Es hat mir die Lektion erteilt. Vielen Dank!
Ola
5
Mein Linter hat sich über diesen Einzeiler beschwert (Rückgabe eines Auftrags), aber dieser funktioniert für mich und ist für mich leichter zu lesen:Object.keys(dict).sort().reduce((r, k) => Object.assign(r, { [k]: dict[k] }), {});
aks.
68

Leute, ich bin im übertragenen Sinne schockiert! Sicher, alle Antworten sind etwas alt, aber niemand hat die Stabilität beim Sortieren erwähnt! Nehmen Sie also mein Bestes, um die Frage selbst zu beantworten und hier auf Details einzugehen. Also werde ich mich jetzt entschuldigen, es wird viel zu lesen sein.

Da es 2018 ist, werde ich nur ES6 verwenden. Die Polyfills sind alle in den MDN-Dokumenten verfügbar, die ich im angegebenen Teil verlinken werde.


Antwort auf die Frage:

Wenn Ihre Schlüssel nur Zahlen sind, können Sie das sortierte Objekt sicher Object.keys()zusammen mit Array.prototype.reduce()zurückgeben:

// 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), {}));

Wenn Sie jedoch mit Zeichenfolgen arbeiten, empfehle ich dringend, Array.prototype.sort()all dies zu verketten :

// 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), {}));

Wenn sich jemand fragt, was Reduzieren bewirkt:

// 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().
}, {});

Bei Bedarf finden Sie hier die Erklärung für den einen Liner:

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

Warum das Sortieren etwas kompliziert ist:

Kurz gesagt, Object.keys()wird ein Array mit der gleichen Reihenfolge zurückgegeben, die wir mit einer normalen Schleife erhalten:

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

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

Object.keys () gibt ein Array zurück, dessen Elemente Zeichenfolgen sind, die den aufzählbaren Eigenschaften entsprechen, die direkt auf dem Objekt gefunden werden. Die Reihenfolge der Eigenschaften entspricht der Reihenfolge, in der die Eigenschaften des Objekts manuell durchlaufen werden.

Nebenbemerkung - Sie können sie auch Object.keys()für Arrays verwenden. Beachten Sie jedoch , dass der Index zurückgegeben wird:

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

Es ist jedoch nicht so einfach wie in diesen Beispielen gezeigt. Objekte der realen Welt können Zahlen und alphabetische Zeichen oder sogar Symbole enthalten (bitte nicht tun).

Hier ist ein Beispiel mit allen in einem Objekt:

// 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' ]

Wenn wir nun Array.prototype.sort()das Array oben verwenden, ändert sich die Ausgabe:

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

Hier ist ein Zitat aus den Dokumenten:

Die sort () -Methode sortiert die Elemente eines Arrays an Ort und Stelle und gibt das Array zurück. Die Sortierung ist nicht unbedingt stabil. Die Standardsortierreihenfolge entspricht den Zeichenfolgen-Unicode-Codepunkten.

Die zeitliche und räumliche Komplexität der Sortierung kann nicht garantiert werden, da sie implementierungsabhängig ist.

Sie müssen sicherstellen, dass einer von ihnen die gewünschte Ausgabe für Sie zurückgibt. In Beispielen aus der Praxis neigen Menschen dazu, Dinge zu verwechseln, insbesondere wenn Sie verschiedene Informationseingaben wie APIs und Datenbanken zusammen verwenden.


Also, was ist die große Sache?

Nun, es gibt zwei Artikel, die jeder Programmierer verstehen sollte:

In-Place-Algorithmus :

In der Informatik ist ein In-Place-Algorithmus ein Algorithmus, der Eingaben ohne Hilfsdatenstruktur transformiert. Für Hilfsvariablen ist jedoch ein geringer zusätzlicher Speicherplatz zulässig. Die Eingabe wird normalerweise von der Ausgabe überschrieben, wenn der Algorithmus ausgeführt wird. Der In-Place-Algorithmus aktualisiert die Eingabesequenz nur durch Ersetzen oder Austauschen von Elementen. Ein Algorithmus, der nicht vorhanden ist, wird manchmal als nicht vorhanden oder nicht vorhanden bezeichnet.

Im Grunde genommen wird unser altes Array überschrieben! Dies ist wichtig, wenn Sie das alte Array aus anderen Gründen beibehalten möchten. Denken Sie also daran.

Sortieralgorithmus

Stabile Sortieralgorithmen sortieren identische Elemente in derselben Reihenfolge, in der sie in der Eingabe erscheinen. Beim Sortieren einiger Arten von Daten wird bei der Bestimmung der Sortierreihenfolge nur ein Teil der Daten untersucht. Im Beispiel für die Kartensortierung rechts werden die Karten beispielsweise nach ihrem Rang sortiert und ihre Farbe wird ignoriert. Dies ermöglicht die Möglichkeit mehrerer verschiedener korrekt sortierter Versionen der ursprünglichen Liste. Stabile Sortieralgorithmen wählen eine davon gemäß der folgenden Regel aus: Wenn zwei Elemente wie die beiden 5 Karten als gleich verglichen werden, bleibt ihre relative Reihenfolge erhalten, sodass dies auch der Fall ist, wenn eines in der Eingabe vor dem anderen kam kommen vor dem anderen in der Ausgabe.

Geben Sie hier die Bildbeschreibung ein

Ein Beispiel für eine stabile Sortierung auf Spielkarten. Wenn die Karten nach Rang mit einer stabilen Sortierung sortiert sind, müssen die beiden 5er in der sortierten Ausgabe, in der sie sich ursprünglich befanden, in derselben Reihenfolge bleiben. Wenn sie mit einer nicht stabilen Sortierung sortiert werden, können die 5er in der entgegengesetzten Richtung enden Reihenfolge in der sortierten Ausgabe.

Dies zeigt, dass die Sortierung richtig ist, sich aber geändert hat. Selbst wenn die Sortierung korrekt ist, müssen wir in der realen Welt sicherstellen, dass wir das bekommen, was wir erwarten! Dies ist sehr wichtig. Denken Sie auch daran. Weitere JavaScript-Beispiele finden Sie in den Dokumenten Array.prototype.sort () - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort

Megajin
quelle
3
Du flippst Rock, danke für diese unglaubliche Antwort. Eines der besten, das ich auf SO gesehen habe. Prost.
Gavin
Wenn Sie nur eine verdammte Methode bereitstellen könnten, die Sie am Ende anwenden können. Tolle Antwort!
mmm
@momomo das Problem ist, je nachdem, was Sie von der Sortierung erwarten, gibt es keine richtige Methode. Sie können diesen Code jedoch einfach aus meiner Antwort verwenden : Object.keys(testObj).sort().reduce((a, c) => (a[c] = testObj[c], a), {}).
Megajin
Ist die Stabilität der Art nicht auf diese Frage anwendbar: Wir sortieren nach Objektschlüssel, und der Schlüssel ist eindeutig. (Um Ihr Kartenbeispiel zu erweitern: Es können niemals zwei 5er im Paket sein, auch wenn sie unterschiedliche Farben haben.)
Darren Cook
@DarrenCook gute Frage! Sie haben Recht, es wird niemals den gleichen Schlüssel in einem Objekt geben. Die Stabilität ist jedoch komplexer als nur die Einzigartigkeit eines Schlüssels. Meistens ist ein Array beim Sortieren von Objekten enthalten. Und dann kann alles instabil werden. Stellen Sie sich ein Kartenspiel mit 5 Spielern vor. Jede Hand wird durch ein Array (um eine individuelle Handsortierung beizubehalten) und die Karten als Objekte dargestellt. Wenn Ihre Karte so aussieht {5: 'hearts'}oder {5: 'spades'}Sie das Array sortieren, wird sie in Spielen wie Rommé möglicherweise instabil. Nicht von verschiedenen Sprachen zu sprechen.
Megajin
29

Das funktioniert bei mir

/**
 * 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;
};
Ashit Vora
quelle
10
Dies ist eigentlich die richtige Antwort auf die vorliegende Frage. Eine vereinfachte Version mit Underscore finden Sie unter: jsfiddle.net/wPjaQ/1
radicand
6
@radicand Nein, diese Antwort ist nicht korrekt. Es wird ein neues Objekt zurückgegeben, das ebenfalls keine Reihenfolge hat.
Paul
3
@radicand In der Praxis auch nicht. Es gibt keine Reihenfolge für die Schlüssel eines Objekts. Wie können Sie also sagen, dass Sie in der Praxis ein Objekt in sortierter Reihenfolge erhalten? Es gibt Ihnen wirklich nur eine flache Kopie des Objekts zurück, das Sie übergeben.
Paul
9
Das ist super falsch. Es funktioniert möglicherweise vorerst, führt jedoch zu einem anderen Webbrowser oder einer anderen Seitenladung im selben Browser. Browser können aus Sicherheitsgründen Objektschlüssel nach dem Zufallsprinzip sortieren. Wenn Sie ein Objekt füllen, werden die Werte abhängig von den Schlüsseln in verschiedenen Speicherbereichen abgelegt, wodurch eine andere Reihenfolge zurückgegeben wird. Wenn dies funktioniert, ist es nur ein Glück für Sie.
Yobert
11
Es hat auch eine unnötige Verwendung von jQuery.
RobG
25

Es ist 2019 und wir haben 2019 einen Weg, dies zu lösen :)

Object.fromEntries(Object.entries({b: 3, a:8, c:1}).sort())
Ben
quelle
2
Wie sortieren wir verschachtelte Objekte nach Schlüssel?
a2441918
@ a2441918 Genauso wie Sie es mit der Funktion sort () tun würden. Schauen Sie sich Folgendes an : developer.mozilla.org/de/docs/Web/JavaScript/Reference/… Object.fromEntries (Object.entries ({b: 3, a: 8, c: 1}). Sort ((k, j ) => k - j))
user2912903
Für TypeScript-Benutzer ist dies für uns noch nicht verfügbar, siehe: github.com/microsoft/TypeScript/issues/30933
tsujp
Netter Einzeiler, aber wie sortiert man die Schlüssel ohne Berücksichtigung der Groß- und Kleinschreibung?
theMaxx
1
@theMaxx Verwenden Sie eine benutzerdefinierte Funktion zum Sortieren, z. B.: `` `Object.fromEntries (Object.entries ({b: 3, a: 8, c: 1}). sort (([key1, val1], [key2, val2]) => key1.toLowerCase (). localeCompare (key2.toLowerCase ())) `` `
Ben
22

Hier ist der 1 Liner

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

Sravan Ganji
quelle
Was zum Teufel ist diese verrückte Syntax? (o[k] = v, o). Warum funktioniert das überhaupt, wo finde ich Dokumente dazu? Es gibt offensichtlich den Parameter ganz rechts zurück, aber warum?
Ntaso
1
@ntaso hier
James
kurze Funktion macht zuerst o[k]gleich vund kehrt dann zurücko
Tahsin Turkoz
19

Dies ist eine alte Frage, aber unter Berücksichtigung der Antwort von Mathias Bynens habe ich eine Kurzversion erstellt, um das aktuelle Objekt ohne großen Aufwand zu sortieren .

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

Nach der Codeausführung werden die Schlüssel für das "ungeordnete" Objekt selbst alphabetisch sortiert.

Sergio Moura
quelle
17

Mit lodash funktioniert dies:

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

Nur Denkanstöße.

Brian M. Hunt
quelle
15

Angenommen, es könnte im VisualStudio-Debugger nützlich sein, der ungeordnete Objekteigenschaften anzeigt.

(function(s){var t={};Object.keys(s).sort().forEach(function(k){t[k]=s[k]});return t})({b:2,a:1,c:3})
Serg
quelle
So großartig, danke loooot
Mugiwara
Nett! Vielen Dank für diese prägnante Lösung.
Con Antonakos
9

Unterstreichungsversion :

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

Wenn Sie Ihrem Browser nicht vertrauen, dass er die Reihenfolge der Schlüssel beibehält, empfehle ich dringend, sich auf ein geordnetes Array von Schlüssel-Wert-gepaarten Arrays zu verlassen.

_.sortBy(_.pairs(c),function(o){return o[0]})
Flavien Volken
quelle
Besser:_.object(_.sortBy(_.pairs(unordered), _.first))
Afanasii Kurakin
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,
});
user3286817
quelle
Vielleicht ist es besser, eine Erklärung für Ihren Code hinzuzufügen.
Aristotll
1
Ruft die Schlüssel des Objekts ab, es handelt sich also um ein Array von Zeichenfolgen. Ich sortiere () und da es sich um ein Array von Zeichenfolgen (Schlüsseln) handelt, reduziere ich sie (mit reduziere () von js Array). Der acc ist anfangs ein leeres Objekt {} (letztes Argument des Reduzierers) und der Reduzierer (Rückruf) weist dem leeren Objekt die Werte des Quellobjekts mit der geordneten Tastenfolge zu.
user3286817
8

Vielleicht etwas elegantere Form:

 /**
     * 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 und das gleiche mit ES6 + -Syntax:

function ksort( src ) {
  const keys = Object.keys( src );
  keys.sort();
  return keys.reduce(( target, key ) => {
        target[ key ] = src[ key ];
        return target;
  }, {});
};
Dmitry Sheiko
quelle
es sortiert nichts. Sie geben immer noch ein Objekt zurück. Sie können nicht garantieren, dass die Objekte in Ihrem Ziel tatsächlich eine Reihenfolge haben. Sie müssen ein Array zurückgeben. jeeezus.
mmm
Das einzige, was Sie hier tun, ist sicherzustellen, dass es sich um ein Set handelt, das nicht optimal ist.
mmm
7

rekursive Sortierung für verschachtelte Objekte und Arrays

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!'
            }
        },
    ]
});
user3286817
quelle
Ich denke, Sie brauchen eine elseda Array.isArray(obj[key])typeof obj[key] === 'object'
drin
Wenn Sie ein Array von Grundelementen haben, wandelt Ihre Funktion die Grundelemente (Zeichenfolge / Zahl) in leere Objekte um. Zu fangen diese Ich habe folgendes gleich zu Beginn Ihrer Funktion: function sortObjectKeys(obj){: if(typeof obj != 'object'){ /* it is a primitive: number/string (in an array) */ return obj; }. Aus if(obj == null || obj == undefined){ return obj; }
Gründen der
4

Wie bereits erwähnt, sind Objekte ungeordnet.

Jedoch...

Sie können diese Redewendung nützlich finden:

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

var kv = [];

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

kv.sort()

Sie können dann durch kv iterieren und tun, was Sie wollen.

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

Hier ist eine saubere Version auf Lodash-Basis, die mit verschachtelten Objekten funktioniert

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

Es wäre noch sauberer, wenn lodash eine toObject()Methode hätte ...

BlueRaja - Danny Pflughoeft
quelle
3

Verwenden Sie einfach lodash, um die Karte zu entpacken und sortBy den ersten Wert von pair und zip erneut, um den sortierten Schlüssel zurückzugeben.

Wenn Sie einen Sortierwert wünschen, ändern Sie den Paarindex auf 1 anstelle von 0

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

Geben Sie hier die Bildbeschreibung ein

Narayanaperumal Gurusamy
quelle
Bitte benutzen Sie den Bearbeitungslink, um zu erklären, wie dieser Code funktioniert, und geben Sie nicht nur den Code an, da eine Erklärung eher zukünftigen Lesern helfen wird. Siehe auch Antworten . Quelle
Jed Fox
3

Sortiert Schlüssel rekursiv unter Beibehaltung von Referenzen.

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

Beispiel:

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}
Brunettdan
quelle
Schöner Ausschnitt! Was ist der Zweck von delete o[e[0]];dort? Können wir nicht einfach zuweisen?
Boyang
Es scheint, als würden nur neue Zuweisungen zu nicht vorhandenen Schlüsseln den Schlüssel am Ende anhängen. Wenn das Löschen auskommentiert ist, werden die Schlüssel nicht sortiert, zumindest nicht in Chrome.
Brunettdan
Das macht Sinn. Vielen Dank! In jedem Fall ist dies eine Art verlorene Ursache, da js Objektschlüssel gemäß den Spezifikationen keine Sequenz haben. Wir nutzen nur obj und log function impl details
Boyang
Ja, ich benutze die Karte, wenn die Reihenfolge der Schlüssel wichtig ist: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
brunettdan
3
Object.keys(unordered).sort().reduce(
    (acc,curr) => ({...acc, [curr]:unordered[curr]})
    , {}
)
Wildhammer
quelle
3

Dies ist eine einfache Lösung für alles, was ich für die JSON-Sortierung benötige.

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;
    }, {});
}
Alan Hape
quelle
2

Verwenden Sie diesen Code, wenn Sie verschachtelte Objekte oder ein verschachteltes Array obj haben.

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;
};
Phani Reddy
quelle
5
Der Autor gibt weder an, dass er jQuery verwendet, noch ist die Frage mit jQuery gekennzeichnet. Es wäre schön, wenn Sie eine Lösung in reinem Javascript hinzufügen würden.
Rusmus
Danke @Phani, genau das habe ich gebraucht
Will Sheppard
2

Lösung:

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

Erläuterung:

Viele JavaScript-Laufzeiten speichern Werte in einem Objekt in der Reihenfolge, in der sie hinzugefügt werden.

Um die Eigenschaften eines Objekts nach ihren Schlüsseln zu sortieren, können Sie die Funktion Object.keys verwenden, die ein Array von Schlüsseln zurückgibt . Das Array von Schlüsseln kann dann nach Array.prototype.sort () sortiert werden. Methode die Elemente eines Arrays an Ort und Stelle (ohne dass sie einer neuen Variablen zugewiesen werden müssen).

Sobald die Schlüssel sortiert sind, können Sie sie einzeln verwenden, um auf den Inhalt des alten Objekts zuzugreifen und ein neues Objekt zu füllen (das jetzt sortiert ist).

Unten finden Sie ein Beispiel für das Verfahren (Sie können es in Ihren Zielbrowsern testen):

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

Hinweis: Object.keys ist eine ECMAScript 5.1-Methode, aber hier ist eine Polyfüllung für ältere Browser:

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;
  };
}
Benny Neugebauer
quelle
2

Ich habe einige Java-Enums auf Javascript-Objekte übertragen.

Diese Objekte haben für mich die richtigen Arrays zurückgegeben. Wenn die Objektschlüssel vom gemischten Typ sind (Zeichenfolge, Int, Zeichen), liegt ein Problem vor.

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"]
Sherali Turdiyev
quelle
2

Einfaches und lesbares Snippet mit lodash.

Sie müssen den Schlüssel nur in Anführungszeichen setzen, wenn Sie sortBy aufrufen. Es muss nicht in Anführungszeichen in den Daten selbst stehen.

_.sortBy(myObj, "key")

Außerdem ist Ihr zweiter zuzuordnender Parameter falsch. Es sollte eine Funktion sein, aber das Zupfen ist einfacher.

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

Es gibt ein großartiges Projekt von @sindresorhus namens Sort-Keys, das fantastisch funktioniert.

Sie können den Quellcode hier überprüfen:

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

Oder Sie können es mit npm verwenden:

$ npm install --save sort-keys

Hier sind auch Codebeispiele aus seiner 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}
fernandopasik
quelle
1

Reine JavaScript-Antwort zum Sortieren eines Objekts. Dies ist die einzige Antwort, von der ich weiß, dass sie mit negativen Zahlen umgeht. Diese Funktion dient zum Sortieren numerischer Objekte.

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

Die Ausgabe ist ein Objekt, das nach diesen Zahlen sortiert ist, wobei neue Schlüssel bei 0 beginnen.

Fall
quelle
1

Nur um es zu vereinfachen und die Antwort von Matt Ball klarer zu machen

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

João Pimentel Ferreira
quelle
1

Ich bin mir nicht sicher, ob dies die Frage beantwortet, aber das ist es, was ich brauchte.

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

Genannt als:

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

Die eine Zeile:

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

Der beste Weg, dies zu tun, ist

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

Sie können zuerst Ihr fast Array-ähnliches Objekt in ein reales Array konvertieren und dann .reverse () verwenden:

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

Der leere Slot am Ende, wenn Ursache, weil Ihr erster Index 1 statt 0 ist. Sie können den leeren Slot mit .length-- oder .pop () entfernen.

Wenn Sie alternativ .reverse ausleihen und für dasselbe Objekt aufrufen möchten, muss es sich um ein vollständig Array-ähnliches Objekt handeln. Das heißt, es benötigt eine Längeneigenschaft:

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

Beachten Sie, dass es dasselbe vollständig Array-ähnliche Objektobjekt zurückgibt, sodass es kein echtes Array ist. Anschließend können Sie mit delete die Eigenschaft length entfernen.

Pedro JR
quelle