Komprimieren Objekthierarchien in JavaScript
-
12-09-2019 - |
Frage
Gibt es eine generische Herangehensweise an verschachtelten Objekten auf einer Ebene „Komprimierung“:
var myObj = {
a: "hello",
b: {
c: "world"
}
}
compress(myObj) == {
a: "hello",
b_c: "world"
}
Ich denke, es würde einige Rekursion beteiligt sein, aber ich dachte, ich brauche nicht das Rad hier neu zu erfinden ...?!
Lösung
function flatten(obj, includePrototype, into, prefix) {
into = into || {};
prefix = prefix || "";
for (var k in obj) {
if (includePrototype || obj.hasOwnProperty(k)) {
var prop = obj[k];
if (prop && typeof prop === "object" &&
!(prop instanceof Date || prop instanceof RegExp)) {
flatten(prop, includePrototype, into, prefix + k + "_");
}
else {
into[prefix + k] = prop;
}
}
}
return into;
}
Sie können, gehören Mitglieder Mitglieder geerbt true
in den zweiten Parameter, indem.
Ein paar Einschränkungen:
-
rekursive Objekte werden nicht funktionieren. Zum Beispiel:
var o = { a: "foo" }; o.b = o; flatten(o);
wird rekursiv, bis es eine Ausnahme auslöst.
-
Wie ruquay Antwort, zieht dieses Array-Elemente aus wie normale Objekteigenschaften. Wenn Sie Arrays intakt halten wollen, fügen Sie "
|| prop instanceof Array
" zu den Ausnahmen. -
Wenn Sie dies auf Objekte aus einem anderen Fenster aufrufen oder Rahmen, Daten und reguläre Ausdrücke werden nicht berücksichtigt, da
instanceof
nicht richtig funktionieren. Sie können das Problem beheben, indem es mit dem Standard-toString Methode wie folgt ersetzt:Object.prototype.toString.call(prop) === "[object Date]" Object.prototype.toString.call(prop) === "[object RegExp]" Object.prototype.toString.call(prop) === "[object Array]"
Andere Tipps
Hier ist ein schneller ein, aber achten Sie, b / c es wird nicht Arbeit w / Arrays und Nullwerte (b / c ihre typeof returns "Objekt").
var flatten = function(obj, prefix) {
if(typeof prefix === "undefined") {
prefix = "";
}
var copy = {};
for (var p in obj) {
if(obj.hasOwnProperty(p)) {
if(typeof obj[p] === "object") {
var tmp = flatten(obj[p], p + "_");
for(var q in tmp) {
if(tmp.hasOwnProperty(q)) {
copy[prefix + q] = tmp[q];
}
}
}
else {
copy[prefix + p] = obj[p];
}
}
}
return copy;
}
var myObj = {
a: "level 1",
b: {
a: "level 2",
b: {
a: "level 3",
b: "level 3"
}
}
}
var flattened = flatten(myObj);
Hier ist eine schnelle Coffee Version basiert off Matthew Crumley Antwort (ich habe nicht mit includePrototype
wie ich es nicht nötig hatte):
flatten = (obj, into = {}, prefix = '', sep = '_') ->
for own key, prop of obj
if typeof prop is 'object' and prop not instanceof Date and prop not instanceof RegExp
flatten prop, into, prefix + key + sep, sep
else
into[prefix + key] = prop
into
Und eine grundlegende Verflachung-Version, die mit wiederholten Separatoren und anderer solchen Verschlagenheit zweifellos scheitern würde:
unflatten = (obj, into = {}, sep = '_') ->
for own key, prop of obj
subKeys = key.split sep
sub = into
sub = (sub[subKey] or= {}) for subKey in subKeys[...-1]
sub[subKeys.pop()] = prop
into
FWIW, verwende ich diese Funktionen Objektgraphen in Redis schieben Hashes, die nur eine einzige Unterstützung Tiefe von Schlüssel / Wert-Paaren.