Ich habe eine verschachtelte Datenstruktur, die Objekte und Arrays enthält. Wie kann ich die Informationen extrahieren, dh auf einen bestimmten oder mehrere Werte (oder Schlüssel) zugreifen?
Zum Beispiel:
var data = {
code: 42,
items: [{
id: 1,
name: 'foo'
}, {
id: 2,
name: 'bar'
}]
};
Wie kann ich auf name
das zweite Element in zugreifen items
?
javascript
arrays
object
nested
data-manipulation
Felix Kling
quelle
quelle
Antworten:
Vorbereitungen
JavaScript hat nur einen Datentyp, der mehrere Werte enthalten kann: Objekt . Ein Array ist eine spezielle Objektform.
(Einfache) Objekte haben die Form
Arrays haben die Form
Sowohl Arrays als auch Objekte legen eine
key -> value
Struktur frei. Schlüssel in einem Array müssen numerisch sein, während jede Zeichenfolge als Schlüssel in Objekten verwendet werden kann. Die Schlüssel-Wert-Paare werden auch als "Eigenschaften" bezeichnet. .Auf Eigenschaften kann entweder mit Punktnotation zugegriffen werden
oder Klammernotation , wenn der Eigenschaftsname kein gültiger JavaScript- Bezeichnername [spec] wäre oder der Name der Wert einer Variablen ist:
Aus diesem Grund kann auf Array-Elemente nur in Klammernotation zugegriffen werden:
Warten Sie ... was ist mit JSON?
JSON ist eine Textdarstellung von Daten, genau wie XML, YAML, CSV und andere. Um mit solchen Daten arbeiten zu können, müssen sie zuerst in JavaScript-Datentypen, dh Arrays und Objekte, konvertiert werden (und wie mit diesen Daten gearbeitet wird, wurde gerade erklärt). Wie JSON analysiert wird, wird in der Frage JSON in JavaScript analysieren erläutert . .
Weiterführendes Lesematerial
Der Zugriff auf Arrays und Objekte ist ein grundlegendes JavaScript-Wissen. Daher ist es ratsam, das MDN-JavaScript-Handbuch zu lesen , insbesondere die Abschnitte
Zugriff auf verschachtelte Datenstrukturen
Eine verschachtelte Datenstruktur ist ein Array oder Objekt, das sich auf andere Arrays oder Objekte bezieht, dh ihre Werte sind Arrays oder Objekte. Auf solche Strukturen kann durch aufeinanderfolgendes Anwenden der Punkt- oder Klammernotation zugegriffen werden.
Hier ist ein Beispiel:
Nehmen wir an, wir wollen auf die zugreifen
name
das zweite Element .So können wir es Schritt für Schritt machen:
Wie wir sehen können,
data
handelt es sich um ein Objekt, daher können wir mithilfe der Punktnotation auf seine Eigenschaften zugreifen. Auf dieitems
Unterkunft wird wie folgt zugegriffen:Der Wert ist ein Array. Um auf sein zweites Element zuzugreifen, müssen wir die Klammernotation verwenden:
Dieser Wert ist ein Objekt und wir verwenden erneut die Punktnotation, um auf die
name
Eigenschaft zuzugreifen . So bekommen wir schließlich:Alternativ hätten wir für jede der Eigenschaften die Klammernotation verwenden können, insbesondere wenn der Name Zeichen enthielt, die ihn für die Verwendung der Punktnotation ungültig gemacht hätten:
Ich versuche, auf eine Immobilie zuzugreifen, bekomme aber nur
undefined
zurück?Meistens
undefined
hat das Objekt / Array beim Abrufen einfach keine Eigenschaft mit diesem Namen.Verwenden Sie
console.log
oderconsole.dir
und überprüfen Sie die Struktur des Objekts / Arrays. Die Eigenschaft, auf die Sie zugreifen möchten, ist möglicherweise tatsächlich für ein verschachteltes Objekt / Array definiert.Was ist, wenn die Eigenschaftsnamen dynamisch sind und ich sie vorher nicht kenne?
Wenn die Eigenschaftsnamen unbekannt sind oder wir auf alle Eigenschaften eines Objekts / von Elementen eines Arrays zugreifen möchten, können wir die
for...in
[MDN] -Schleife für Objekte und diefor
[MDN] -Schleife für Arrays verwenden, um alle Eigenschaften / Elemente zu durchlaufen.Objekte
Um alle Eigenschaften von zu durchlaufen
data
, können wir das Objekt folgendermaßen durchlaufen :Abhängig davon, woher das Objekt stammt (und was Sie tun möchten), müssen Sie möglicherweise in jeder Iteration testen, ob die Eigenschaft wirklich eine Eigenschaft des Objekts oder eine geerbte Eigenschaft ist. Sie können dies mit
Object#hasOwnProperty
[MDN] tun .Alternativ zu
for...in
withhasOwnProperty
können SieObject.keys
[MDN] verwenden , um ein Array von Eigenschaftsnamen abzurufen :Arrays
Um alle Elemente des
data.items
Arrays zu durchlaufen , verwenden wir einefor
Schleife:Man könnte auch verwenden
for...in
, um über Arrays zu iterieren, aber es gibt Gründe, warum dies vermieden werden sollte: Warum ist 'for (var item in list)' bei Arrays, die in JavaScript als schlechte Praxis angesehen werden? .Mit der zunehmenden Browserunterstützung von ECMAScript 5 wird auch die Array-Methode
forEach
[MDN] zu einer interessanten Alternative:In Umgebungen, die ES2015 (ES6) unterstützen, können Sie auch die [MDN] -Schleife verwenden, die nicht nur für Arrays, sondern für alle iterierbaren Elemente funktioniert :
for...of
In jeder Iteration
for...of
gibt uns direkt das nächste Element der Iterable, es gibt keinen "Index", auf den zugegriffen oder der verwendet werden kann.Was ist, wenn mir die "Tiefe" der Datenstruktur unbekannt ist?
Zusätzlich zu unbekannten Schlüsseln ist möglicherweise auch die "Tiefe" der Datenstruktur (dh wie viele verschachtelte Objekte) unbekannt. Wie auf tief verschachtelte Eigenschaften zugegriffen wird, hängt normalerweise von der genauen Datenstruktur ab.
Wenn die Datenstruktur jedoch sich wiederholende Muster enthält, z. B. die Darstellung eines Binärbaums, umfasst die Lösung normalerweise den rekursiven Zugriff [Wikipedia] auf jede Ebene der Datenstruktur.
Hier ist ein Beispiel, um den ersten Blattknoten eines Binärbaums zu erhalten:
Code-Snippet anzeigen
Eine allgemeinere Möglichkeit, auf eine verschachtelte Datenstruktur mit unbekannten Schlüsseln und unbekannter Tiefe zuzugreifen, besteht darin, den Typ des Werts zu testen und entsprechend zu handeln.
Hier ist ein Beispiel, das alle primitiven Werte innerhalb einer verschachtelten Datenstruktur zu einem Array hinzufügt (vorausgesetzt, es enthält keine Funktionen). Wenn wir auf ein Objekt (oder Array) stoßen, rufen wir
toArray
diesen Wert einfach erneut auf (rekursiver Aufruf).Code-Snippet anzeigen
Helfer
Da die Struktur eines komplexen Objekts oder Arrays nicht unbedingt offensichtlich ist, können wir den Wert bei jedem Schritt überprüfen, um zu entscheiden, wie Sie sich weiter bewegen möchten.
console.log
[MDN] undconsole.dir
[MDN] helfen uns dabei. Zum Beispiel (Ausgabe der Chrome-Konsole):Hier sehen wir, dass dies
data.items
ein Array mit zwei Elementen ist, die beide Objekte sind. In der Chrome-Konsole können die Objekte sogar sofort erweitert und überprüft werden.Dies sagt uns, dass
data.items[1]
es sich um ein Objekt handelt, und nachdem wir es erweitert haben, sehen wir, dass es drei Eigenschaften hatid
,name
und__proto__
. Letzteres ist eine interne Eigenschaft, die für die Prototypkette des Objekts verwendet wird. Die Prototypkette und die Vererbung sind für diese Antwort jedoch nicht zulässig.quelle
let object = {a: 1, b: 2, c: { a: 3, b: 4 }};
, wird in diesem Fall ein Array zurückgegeben, das ein Array für jedes verschachtelte Objekt enthält.[ 1, 2, [ 3, 4 ] ]
Wäre es nicht besser, im rekursiven Aufruf concat anstelle von push zu verwenden? (erfordert, dass das Ergebnis veränderlich ist)Sie können auf diese Weise darauf zugreifen
oder
Beide Wege sind gleich.
quelle
Wenn Sie versuchen,
item
über die Beispielstruktur auf eine zuzugreifen,id
odername
ohne die Position im Array zu kennen, verwenden Sie am einfachsten die Bibliothek underscore.js :Nach meiner Erfahrung werden Funktionen höherer Ordnung anstelle von
for
oder verwendetfor..in
Schleifen zu Code, der einfacher zu verstehen und daher besser zu warten ist.Nur meine 2 Cent.
quelle
Objekte und Arrays verfügen über zahlreiche integrierte Methoden, die Sie bei der Datenverarbeitung unterstützen können.
Hinweis: In vielen der Beispiele , die ich bin mit Pfeil Funktionen . Sie ähneln Funktionsausdrücken , binden den
this
Wert jedoch lexikalisch.Object.keys()
,Object.values()
(ES 2017) undObject.entries()
(ES 2017)Object.keys()
Gibt ein Array von Objektschlüsseln zurück,Object.values()
gibt ein Array von Objektwerten zurück undObject.entries()
gibt ein Array von Objektschlüsseln und entsprechenden Werten in einem Format zurück[key, value]
.Object.entries()
mit einer For-of-Schleife und einer DestrukturierungszuweisungEs ist sehr praktisch, das Ergebnis
Object.entries()
mit einer For-of-Schleife und einer Destrukturierungszuweisung zu wiederholen .Mit der For-of-Schleife können Sie Array-Elemente iterieren. Die Syntax ist
for (const element of array)
(wir ersetzen könnenconst
mitvar
oderlet
, aber es ist besser zu nutzen ,const
wenn wir nicht ändern wollenelement
).Mit der Destrukturierungszuweisung können Sie Werte aus einem Array oder Objekt extrahieren und Variablen zuweisen. In diesem Fall
const [key, value]
bedeutet dies , dass wir anstelle des[key, value]
Arrayselement
das erste Element dieses Arrayskey
und das zweite Element zuweisenvalue
. Es ist äquivalent dazu:Wie Sie sehen, macht die Destrukturierung dies viel einfacher.
Array.prototype.every()
undArray.prototype.some()
Die
every()
Methode gibt zurück,true
wenn die angegebene Rückruffunktiontrue
für jedes Element des Arrays zurückgegeben wird. Diesome()
Methode wird zurückgegeben,true
wenn die angegebene Rückruffunktiontrue
für ein (mindestens ein) Element zurückgegeben wird.Array.prototype.find()
undArray.prototype.filter()
Die
find()
Methode gibt das erste Element zurück, das die bereitgestellte Rückruffunktion erfüllt. Diefilter()
Methode gibt ein Array aller Elemente zurück, das die bereitgestellte Rückruffunktion erfüllt.Array.prototype.map()
Die
map()
Methode gibt ein Array mit den Ergebnissen des Aufrufs einer bereitgestellten Rückruffunktion für die Array-Elemente zurück.Array.prototype.reduce()
Die
reduce()
Methode reduziert ein Array auf einen einzelnen Wert, indem die bereitgestellte Rückruffunktion mit zwei Elementen aufgerufen wird.Die
reduce()
Methode verwendet einen optionalen zweiten Parameter, der der Anfangswert ist. Dies ist nützlich, wenn das Array, das Sie aufrufenreduce()
können, null oder ein Element enthält. Wenn wir beispielsweise eine Funktion erstellen möchten,sum()
die ein Array als Argument verwendet und die Summe aller Elemente zurückgibt, können wir sie folgendermaßen schreiben:quelle
Object.keys(data["items"]).forEach(function(key) { console.log(data["items"][key].id); console.log(data["items"][key].name); });
Manchmal kann es wünschenswert sein, mit einer Zeichenfolge auf ein verschachteltes Objekt zuzugreifen. Der einfache Ansatz ist zum Beispiel die erste Ebene
Dies ist jedoch bei komplexen JSON häufig nicht der Fall. Wenn json komplexer wird, werden auch die Ansätze zum Finden von Werten innerhalb des json komplexer. Ein rekursiver Ansatz für die Navigation im JSON ist am besten, und wie diese Rekursion genutzt wird, hängt von der Art der Daten ab, nach denen gesucht wird. Wenn es sich um bedingte Anweisungen handelt, wird eine JSON-Suche durchgeführt ein gutes Werkzeug sein.
Wenn die Eigenschaft, auf die zugegriffen wird, bereits bekannt ist, der Pfad jedoch komplex ist, z. B. in diesem Objekt
Und Sie wissen, dass Sie das erste Ergebnis des Arrays im Objekt erhalten möchten, das Sie möglicherweise verwenden möchten
Dies führt jedoch zu einer Ausnahme, da keine Eigenschaft eines Objekts mit diesem Namen vorhanden ist. Die Lösung, um dies nutzen zu können, wäre, den Baumaspekt des Objekts zu reduzieren. Dies kann rekursiv erfolgen.
Jetzt kann das komplexe Objekt abgeflacht werden
Hier wird ein
jsFiddle Demo
Ansatz verwendet.quelle
obj["arr[0].name"]
anstelle von verwendenobj.arr[0].name
? Mit Ausnahme der Serialisierung müssen / wollen Sie sich kaum mit abgeflachten Objekten befassen .Diese Frage ist ziemlich alt, also als zeitgemäßes Update. Mit dem Start von ES2015 gibt es Alternativen, um die benötigten Daten zu erhalten. Es gibt jetzt eine Funktion namens Objektzerstörung für den Zugriff auf verschachtelte Objekte.
Im obigen Beispiel wird eine
secondName
vomname
Schlüssel aufgerufene Variable aus einem Array namens "items
Lonely" erstellt,
Sprichwort überspringt das erste Objekt im Array.Insbesondere ist es für dieses Beispiel wahrscheinlich übertrieben, da ein einfacher Array-Zugriff leichter zu lesen ist, aber es ist nützlich, wenn Objekte im Allgemeinen auseinandergebrochen werden.
Dies ist eine sehr kurze Einführung in Ihren speziellen Anwendungsfall. Destrukturierung kann eine ungewöhnliche Syntax sein, an die Sie sich zunächst gewöhnen müssen. Ich würde empfehlen, Mozillas Destructuring Assignment-Dokumentation zu lesen , um mehr zu erfahren.
quelle
Um auf ein verschachteltes Attribut zuzugreifen, müssen Sie dessen Namen angeben und dann das Objekt durchsuchen.
Wenn Sie den genauen Pfad bereits kennen, können Sie ihn wie folgt in Ihrem Skript fest codieren:
diese funktionieren auch -
Wenn Sie den genauen Namen vorher nicht kennen oder ein Benutzer derjenige ist, der den Namen für Sie bereitstellt. Dann ist ein dynamisches Durchsuchen der Datenstruktur erforderlich. Einige schlugen hier vor, dass die Suche mit einer
for
Schleife durchgeführt werden kann, aber es gibt eine sehr einfache Möglichkeit, einen Pfad mit zu durchlaufenArray.reduce
.Der Pfad ist eine Möglichkeit zu sagen: Nehmen Sie zuerst das Objekt mit dem Schlüssel
items
, der zufällig ein Array ist. Nehmen Sie dann das1
Element -st (0 Index-Arrays). Nehmen Sie zuletzt das Objekt mit dem Schlüsselname
in das Array-Element, das zufällig die Zeichenfolge istbar
.Wenn Sie einen sehr langen Weg haben, können Sie dies sogar nutzen
String.split
, um all dies zu vereinfachen -Dies ist einfach nur JavaScript, ohne Bibliotheken von Drittanbietern wie jQuery oder lodash zu verwenden.
quelle
oder
Verwenden Sie grundsätzlich einen Punkt zwischen jedem Nachkommen, der sich darunter entfaltet, und wenn Sie Objektnamen aus zwei Zeichenfolgen haben, müssen Sie die Notation ["obj Name"] verwenden. Andernfalls würde nur ein Punkt ausreichen;
Quelle: https://learn.freecodecamp.org/javascript-algorithms-and-data-structures/basic-javascript/accessing-nested-objects
Um dies hinzuzufügen, würde der Zugriff auf verschachtelte Arrays folgendermaßen erfolgen:
Quelle: https://learn.freecodecamp.org/javascript-algorithms-and-data-structures/basic-javascript/accessing-nested-arrays/
Ein weiteres nützlicheres Dokument, das die obige Situation darstellt: https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Basics#Bracket_notation
Immobilienzugriff über Dot Walking: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Property_Accessors#Dot_notation
quelle
Sie könnten folgende
lodash _get
Funktion verwenden:quelle
Die Verwendung von JSONPath ist eine der flexibelsten Lösungen, wenn Sie bereit sind, eine Bibliothek einzuschließen : https://github.com/s3u/JSONPath (Knoten und Browser)
Für Ihren Anwendungsfall wäre der JSON-Pfad:
damit:
quelle
Für den Fall, dass jemand diese Frage 2017 oder später besucht und nach einem leicht zu merkenden Weg sucht , finden Sie hier einen ausführlichen Blog-Beitrag zum Zugriff auf verschachtelte Objekte in JavaScript, ohne von ihm verwirrt zu werden
Die Eigenschaft 'foo' von undefined kann nicht gelesen werden Fehlers werden
1. Oliver Steeles verschachteltes Objektzugriffsmuster
Am einfachsten und saubersten ist es, das Zugriffsmuster für verschachtelte Objekte von Oliver Steele zu verwenden
Mit dieser Notation werden Sie nie begegnen
Die Eigenschaft 'name' von undefined kann nicht gelesen werden .
Grundsätzlich prüfen Sie, ob ein Benutzer vorhanden ist. Wenn nicht, erstellen Sie im laufenden Betrieb ein leeres Objekt. Auf diese Weise wird auf den Schlüssel der nächsten Ebene immer von einem vorhandenen oder leeren Objekt aus zugegriffen , jedoch niemals von undefiniert.
2. Greifen Sie mit Array Reduce auf verschachtelte Objekte zu
Um auf verschachtelte Arrays zugreifen zu können, können Sie Ihr eigenes Array schreiben.
Es gibt auch einen exzellenten Typ, der nur minimale Bibliotheksfehler verarbeitet , der all dies für Sie erledigt.
quelle
((user || {}).address || new Array(3))[1].name
...[1].bar
würde dies zu einem Fehler führen, wenn das Element1
nicht vorhanden wäre. Aber das ist auch der Fall,....foo.bar
wennfoo
es nicht existiert. Sie müssen auch den Zugriff "bewachen"1
, genau wie Sie jeden anderen Zugang zu Eigentum "bewachen". Ein Array ist nur ein Objekt. Ein "Array-Element" ist nur eine Eigenschaft. Richtig angewendet wäre es(((user || {}).address || {})[1] || {}).name
.Ich bevorzuge JQuery. Es ist sauberer und leicht zu lesen.
quelle
Zugriff auf dynamisch mehrstufige Objekte.
Arbeitsgeige: https://jsfiddle.net/andreitodorut/3mws3kjL/
quelle
Wenn Sie nach einem oder mehreren Objekten suchen, die bestimmte Kriterien erfüllen, haben Sie mit query-js einige Optionen
Es gibt auch ein
single
und einsingleOrDefault
, wie sie funktionierenfirst
undfirstOrDefault
jeweils. Der einzige Unterschied ist, dass sie werfen, wenn mehr als eine Übereinstimmung gefunden wird.Zur weiteren Erläuterung von query-js können Sie mit diesem Beitrag beginnen
quelle
Der Unterstrich js Weg
Dies ist eine JavaScript-Bibliothek, die eine ganze Reihe nützlicher
functional programming
Helfer bereitstellt, ohne integrierte Objekte zu erweitern.Lösung:
quelle
Alte Frage, aber wie niemand erwähnte lodash (nur unterstreichen).
Falls Sie in Ihrem Projekt bereits lodash verwenden, halte ich dies in einem komplexen Beispiel für eine elegante Möglichkeit:
Opt 1
gleich wie:
Opt 2
Der Unterschied zwischen der ersten und der zweiten Option besteht in der Option 1 wenn eine der Eigenschaften im Pfad fehlt (undefiniert), kein Fehler angezeigt wird, der dritte Parameter zurückgegeben wird.
Für Array Filter hat lodash
_.find()
aber ich würde lieber das reguläre verwendenfilter()
. Aber ich denke immer noch, dass die obige Methode sehr_.get()
nützlich ist, wenn Sie mit wirklich komplexen Daten arbeiten. Ich war in der Vergangenheit mit sehr komplexen APIs konfrontiert und es war praktisch!Ich hoffe, es kann nützlich sein, wer nach Optionen sucht, um wirklich komplexe Daten zu manipulieren, die der Titel impliziert.
quelle
Ich glaube nicht, dass der Fragesteller nur ein verschachteltes Objekt einer Ebene betrifft. Daher präsentiere ich die folgende Demo, um zu demonstrieren, wie auf den Knoten eines tief verschachtelten JSON-Objekts zugegriffen werden kann. Also gut, lasst uns den Knoten mit der ID '5' finden.
quelle
Sie können die Syntax verwenden,
jsonObject.key
um auf den Wert zuzugreifen. Wenn Sie von einem Array aus auf einen Wert zugreifen möchten, können Sie die Syntax verwendenjsonObjectArray[index].key
.Hier sind die Codebeispiele für den Zugriff auf verschiedene Werte, um Ihnen die Idee zu geben.
quelle
Dynamischer Ansatz
In der folgenden
deep(data,key)
Funktion können Sie eine beliebigekey
Zeichenfolge verwenden - in Ihrem Fallitems[1].name
(Sie können die Array-Notation[i]
auf jeder Ebene verwenden) - wenn der Schlüssel ungültig ist, wird undefined zurückgegeben.Code-Snippet anzeigen
quelle
Ein pythonischer, rekursiver und funktionaler Ansatz zum Entschlüsseln beliebiger JSON-Bäume:
Dabei handelt es sich bei den Daten um eine Python-Liste (analysiert aus einer JSON-Textzeichenfolge):
quelle
Mit der grep- Funktion von jQuery können Sie durch ein Array filtern:
quelle
quelle
Im Jahr 2020 können Sie @ babel / plugin-comment-optional-chaining verwenden. Es ist sehr einfach, auf verschachtelte Werte in einem Objekt zuzugreifen.
https://babeljs.io/docs/en/babel-plugin-proposal-optional-chaining
https://github.com/tc39/proposal-optional-chaining
quelle
Meine
stringdata
kommt aus der PHP-Datei, aber trotzdem gebe ich hier in anvar
. Wenn ich meinenobj
JSON direkt einnehme , wird nichts angezeigt, weshalb ich meine JSON-Datei alsvar obj=JSON.parse(stringdata);
so nach , dass ich bekommenmessage
obj und in Alert - Box zeigen , dann bekomme ichdata
das ist Json - Array und Speicher in einem varibleArrObj
dann las ich das erste Objekt dieser Array mit Schlüssel-Wert wie folgtArrObj[0].id
quelle
stringjson
es sich nicht um eine Zeichenfolge handelt.Die Verwendung von lodash wäre eine gute Lösung
Ex:
quelle