Pergunta

Existe uma abordagem genérica para "comprimir" objetos aninhados a um único nível:

var myObj = {
    a: "hello",
    b: {
        c: "world"
    }
}

compress(myObj) == {
    a: "hello",
    b_c: "world"
}

Eu acho que haveria algum recursão envolvido, mas eu percebi que eu não precisa reinventar a roda aqui ...!?

Foi útil?

Solução

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

Você pode incluir membros membros herdados, passando true para o segundo parâmetro.

Algumas advertências:

  • objetos recursiva não vai funcionar. Por exemplo:

    var o = { a: "foo" };
    o.b = o;
    flatten(o);
    

    irá recorrer até que ele lança uma exceção.

  • A resposta de como ruquay, este puxa elementos da matriz assim como propriedades de objetos normais. Se você quiser manter matrizes intacta, adicione "|| prop instanceof Array" para as exceções.

  • Se você chamar isso em objetos de uma janela ou quadro diferente, datas e expressões regulares não será incluído, pois instanceof não irá funcionar corretamente. Você pode corrigir isso, substituindo-o com o método toString padrão como este:

    Object.prototype.toString.call(prop) === "[object Date]"
    Object.prototype.toString.call(prop) === "[object RegExp]"
    Object.prototype.toString.call(prop) === "[object Array]"
    

Outras dicas

Aqui está um rápido, mas cuidado, b / c ele irá não trabalho w / matrizes e valores nulos (b / c seus typeof retorna "objeto").

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);
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top