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 ...?!

War es hilfreich?

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.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top