Objekte mit Array mischen
ebody
- javascript
Hallo,
es handelt sich um einen Beispielcode.
Ich möchte eine XML Datei auslesen und die Werte in einem Objekt speichern. Einige "Knoten" der XML enthalten den gleichen Namen, die weiteren Elemente aber unterschiedliche Werte.
Beispiel XML:
...
<auto>
<marke>dacia</marke>
<farbe>rot</farbe>
<preis>8.000€</preis>
</auto>
<auto>
<marke>dacia</marke>
<farbe>schwarz</farbe>
<preis>11.000€</preis>
</auto>
<auto>
<marke>dacia</marke>
<farbe>blau</farbe>
<preis>10.000€</preis>
</auto>
<auto>
<marke>porsche</marke>
<farbe>rot</farbe>
<preis>50.000€</preis>
</auto>
<auto>
<marke>porsche</marke>
<farbe>schwarz</farbe>
<preis>60.000€</preis>
</auto>
...
Ich möchte das Objekt so erstellen, dass ich auf das Objekt und die Marke zugreifen kann und mir alle Varianten der Marke gezeigt werden.
Um das zu testen habe ich diesen Code verwendet:
var objCar2 = {"dacia":[],"porsche":[]};
objCar2.dacia.push({"Farbe":"rot","Preis:":"8.000€"});
objCar2.dacia.push({"Farbe":"scwarz","Preis:":"11.000€"});
objCar2.dacia.push({"Farbe":"blau","Preis:":"10.000€"});
objCar2.porsche.push({"Farbe":"rot","Preis:":"50.000€"});
objCar2.porsche.push({"Farbe":"scwarz","Preis:":"60.000€"});
console.log("objCar2 dacia: ", objCar2.dacia);
console.log("objCar2 porsche: ", objCar2.porsche);
Die Ausgabe in der WebDev Console zeigt alles richtig an, aber
Gruß ebody
Tach!
- Ist es überhaupt "erlaubt" Arrays in Objekte zu mischen?
Gibts Syntaxfehler? Ein Array ist in Javascript auch nichts weiter als ein spezielles Objekt.
- Habt Ihr eine bessere Lösung / Optimierungs Tipps?
Dacia und Porsche sind keine Schlüssel sondern Werte. Mach lieber ein Array für Autos, und da liegen dann gleichberechtigt alle drin, egal welche Typen und Ausstattung sie haben. Auf Teile davon kann man mit Methoden wie filter() zugreifen.
dedlfix.
Hi,
Syntaxfehler gab es keine.
Wenn ich jetzt aber ein Objekt haben möchte und die Marke soll ein Schlüssel sein, wie kann man dem gleichen Schlüssel dann weitere Eigenschaften zufügen?
var autos = {};
autos["Dacia"] = {"Farbe":"rot","Preis:":"8.000€"};
autos["Dacia"] = {"Farbe":"scwarz","Preis:":"11.000€"};
autos["Dacia"] = {"Farbe":"blau","Preis:":"10.000€"};
console.log("autos: ", autos["Dacia"]); // Gibt die zuletzt hinzugefügten Eigenschaften aus
In diesem Beispiel würden die Eigenschaften immer überschrieben.
Mich interessiert speziell, wie man es in so einem Fall schreiben müsste. Evtl. wäre ein Array sinvoller, aber wie müsste man es in diesem Fall machen?
Gruß ebody
Tach!
Wenn ich jetzt aber ein Objekt haben möchte und die Marke soll ein Schlüssel sein, wie kann man dem gleichen Schlüssel dann weitere Eigenschaften zufügen?
Man kann einer Eigenschaft nur einen Wert zuweisen. Wenn es mehrere sein sollen, muss da ein Container drumherum sein, also ein weiteres Objekt. Oder ein Objekt vom Typ Array, also ein einfach gesagt ein Array.
Das war schon richtig so in deinem Beispiel vom Eingangsposting.
dedlfix.
Hallo ebody,
grundsätzlich bist Du frei, ein Array zu erstellen, das Objekte enthält, deren Eigenschaften Arrays sind, worin sich wieder Objekte befinden... ad nauseam (oder insaniam, je nach dem...)
Du erstellt deine Objekte mit dem JavaScript-Konstrukt „Objektliteral“. Das ist völlig ok, aber deine Art es aufzuschreiben ist ungewöhnlich.
// Deins
{"Farbe":"rot","Preis:":"8.000€"}
// Mein Vorschlag:
{ farbe: "rot", preis: 8000 }
Warum?
Ob es für deinen Zweck sinnvoll ist, pro Marke ein eigenes Array zu bilden, hat dedlfix bereits bezweifelt. Wenn Du die Marke mit ans Auto-Objekt hängst und nur ein Array bildest, kannst Du bei Bedarf dieses Array filtern (z.B. mit der filter-Funktion, die zum Array-Prototyp gehört, oder mit einer Generatorfunktion. Eine Vorsortierung in ein Array pro Marke dürfte nur in Ausnahmefällen sinnvoll sein (sehr viele Autos und verschiedene Marken, häufiges Iterieren und Filtern auf Marke).
var autos = [
{ marke: "Dacia", farbe: "rot" , preis: 8000},
{ marke: "Dacia", farbe: "gelb", preis: 2000},
{ marke: "Dacia", farbe: "blau", preis: 17000},
{ marke: "Porsche", farbe: "silber", preis: 80000},
{ marke: "Mercedes", farbe: "pink", preis: 120000}
];
// 1. Markenindex bilden (als Eigenschaften eines marken-Objekts)
marken = { };
for (let a of autos) {
console.log("Register " + a.marke);
marken[a.marke] = 1;
}
// 2. Gefundene Marken auflisten
for (let m of Object.getOwnPropertyNames(marken).sort()) {
console.log("Marke: " + m);
for (let a of autos) {
if (a.marke == m)
console.log(" Farbe: " + a.farbe
+ ", Preis: "
+ a.preis.toLocaleString(undefined, { style:"currency", currency: "EUR"}))
}
}
// for...of iteriert über die Elemente eines Arrays.
// Es gibt natürlich auch andere Möglichkeiten, das zu tun...
Rolf
Andere Schreibkonventionen sind PascalCase, snake_case, kebab-case. Den Namen "Kebab Case" habe ich eben erst in der Wikipedia gesehen als ich eine Referenz zum casing suchte; Klassennamen in HTML folgen typischerweise dem kebab-case. ↩︎
Hallo Rolf,
vielen Dank für das Beispiel, es hilft mir weiter und zeigt mir eine gute Variante. Bitte deute meine Frage jetzt nicht so, dass ich Deinen oder Eure Beiträge irgendwie ignoriere. Ich probiere gerade einfach verschiedenes dies bzgl. aus und dabei stoße ich immer wieder auf neue Fragen.
Eigenschaftennamen müssen nur in Anführungszeichen stehen wenn sie keinen erlaubten JavaScript-Namen bilden.
Wenn man jetzt nach diesem Beispiel gehen würde
var autos = {dacia:[],porsche:[]};
autos .dacia.push({"Farbe":"rot","Preis:":"8.000€"});
autos .dacia.push({"Farbe":"scwarz","Preis:":"11.000€"});
autos .dacia.push({"Farbe":"blau","Preis:":"10.000€"});
autos .porsche.push({"Farbe":"rot","Preis:":"50.000€"});
autos .porsche.push({"Farbe":"scwarz","Preis:":"60.000€"});
console.log("autos dacia: ", autos .dacia);
console.log("autos porsche: ", autos .porsche);
Und das Array (die Marke) soll dem Objekt über eine Variable hinzugefügt werden, wie müsste man das dann schreiben?
// Ein leeres Objekt
var autos = {};
// Die Variable deren Wert im Objekt als Array (Name) gespeichert werden soll
var varMarke = "dacia";
// Soll ein Array als Wert hinzugefügt werden
autos = {varMarke:[]};
In dem Fall würde das Objekt ein Array mit dem Namen varMarke
und nicht dacia
enthalten.
Gruß ebody
Hallo ebody,
var autos = {};
var varMarke = "dacia";
autos = {varMarke:[]};
Dieser Code hat zwei Probleme. Erstens möchtest Du dem Objekt in autos
eine Eigenschaft hinzufügen. Du ersetzt aber das ganze Objekt. Zweitens möchtest Du, wie schon erkannt, den Namen der Eigenschaft aus einer Variablen holen und nicht statisch setzen.
Wenn Eigenschaftsnamen variabel sind, muss man mit der [] Notation arbeiten. Ein Objektliteral mit variablen Eigenschaftsnamen ist überhaupt nicht möglich (es sei denn, man arbeitet mit fiesen Tricks wie eval(), aber das gehört zu den ugly parts von JavaScript).
So geht es:
// Im Objektliteral
var autos = { Opel: [] };
// Hinzufügen von Eigenschaften mit statischen Namen in Punkt oder [] Notation
autos.Mercedes = [];
autos["Porsche"] = [];
// Hinzufügen von Eigenschaften mit variablen Namen nur in [] Notation
var marke = "Dacia";
autos[marke] = [];
Eine Art "Objekt-Merge" Operator, also sowas wie
var autos = { porsche: [] };
autos += { dacia: [] }; // KEIN JAVASCRIPT !
gibt es in JavaScript nicht. Aber ES2015 führt hierfür die Object.assign Methode ein.
Rolf
Tach!
// 1. Markenindex bilden (als Eigenschaften eines marken-Objekts) marken = { }; for (let a of autos) { console.log("Register " + a.marke); marken[a.marke] = 1; }
In modernem Javascript kann man für marken
ein Set nehmen, da hat man gleich was ordentliches zum Iterieren und muss nicht mit solchen Hilfskonstrukten arbeiten: Object.getOwnPropertyNames(marken)
. Zur Not kann man daraus auch ein richtiges Array machen: Array.from(the_set)
.
dedlfix.
hallo
// 2. Gefundene Marken auflisten for (let m of Object.getOwnPropertyNames(marken).sort()) { console.log("Marke: " + m); for (let a of autos) { if (a.marke == m) console.log(" Farbe: " + a.farbe + ", Preis: " + a.preis.toLocaleString(undefined, { style:"currency", currency: "EUR"})) } }
Toll. Ich kann zwar kein Chinesisch, aber Preise kann ich in einer mir unverständlichen Form publizieren. Wenn das rechtlich mal nicht schief läuft.
Hallo beatovich,
hättest Du dies hier besser gefunden? Oder eine Callback-in-Callback Orgie mit Array.prototype.foreach?
// 2. Gefundene Marken auflisten
var markennamen = Object.getOwnPropertyNames(marken).sort();
for (var m=0; m<markennamen.length; m++) {
console.log("Marke: " + markennamen[m]);
for (var au=0; au<autos.length; au++) {
if (autos[au].marke == markennamen[m])
console.log(" Farbe: " + autos[au].farbe
+ ", Preis: "
+ formatEuroPreis(autos[au].preis));
}
}
function formatEuroPreis(preis) {
// do it somehow
return formatierterPreis;
}
Rolf
hallo
Hallo beatovich,
hättest Du dies hier besser gefunden? Oder eine Callback-in-Callback Orgie mit Array.prototype.foreach?
// 2. Gefundene Marken auflisten var markennamen = Object.getOwnPropertyNames(marken).sort(); for (var m=0; m<markennamen.length; m++) { console.log("Marke: " + markennamen[m]); for (var au=0; au<autos.length; au++) { if (autos[au].marke == markennamen[m]) console.log(" Farbe: " + autos[au].farbe + ", Preis: " + formatEuroPreis(autos[au].preis)); } } function formatEuroPreis(preis) { // do it somehow return formatierterPreis; }
Lass mich so antworten:
Falls ich als Beamter dich auffordere, dich zu einem bestimmten Termin einzufinden, so werde ich den Termin gewiss NICHT nach deinem locale angeben, sondern nach einer Methode, die objektiv ist.
Hi,
selbstverständlich kann eine Eigenschaft mehrere Werte beinhalten. Z.B. Zubehörteile oder Sonderausstattungen. Verschiedene Farben oder Größen jedoch sind Variationen, so hat ein Artikel nur eine Farbe und eine Größe.
MfG