展开JS对象并转换数组

3

我有一个函数用于将对象展开成如下形式:

let object = {
  a: 1,
  b: [
   { c: 2 },
   { c: 3 }
  ]
};

flatten(object)
// returns {
  'a': 1,
  'b.0.c': 2,
  'b.1.c': 3
}

我需要展开对象,但也需要将数组还原到之前的状态。我有以下代码:
  unflatten(obj) {
    let final = {};

    for (let prop in obj) {
      this.assign(final, prop.split('.'), obj[prop]);
    }

    return final;
  }

  assign(final, path, value) {
     let lastKeyIndex = path.length-1;
     for (var i = 0; i < lastKeyIndex; ++ i) {
       let key = path[i];
       if (!(key in final)) {
         final[key] = {};
       }
       final = final[key];
     }
     final[path[lastKeyIndex]] = value;
  }

这基本上是有效的,但它对数组的处理方式如下:

{
  a: 1,
  b: { // Notice how b's value is now an object
   "0": { c: 2 }, // Notice how these now have a key corresponding to their index
   "1": { c: 3 }
  }
}

相较之前,我需要b仍然是一个数组:

{
  a: 1,
  b: [
   { c: 2 },
   { c: 3 }
  ]
}

我不知道该从哪里继续了。它需要能够处理任意数量的数组,例如:

'a.b.0.c.0.d',
'a.b.0.c.1.d',
'a.b.1.c.0.d',
'a.b.1.c.1.d',
'a.b.1.c.2.d',
// etc

需要使用原生JS,但使用es2015也可以。假定任何数字键都是数组的一部分。

如果有任何建议,将不胜感激!

2个回答

1
当您发现key不在final中时,应检查路径中的下一个键是否只包含数字(使用正则表达式),如果是,则将其分配给数组而不是对象:
if (!(key in final)) {
  final[key] = /^\d+$/.test(path[i + 1]) ? [] : {};
}

let object = {
  a: 1,
  b: [{
      c: 2
    },
    {
      c: 3
    }
  ]
};

let flattened = {
  'a': 1,
  'b.0.c': 2,
  'b.1.c': 3
}

function unflatten(obj) {
  let final = {};

  for (let prop in obj) {
    assign(final, prop.split('.'), obj[prop]);
  }

  return final;
}

function assign (final, path, value) {
  let lastKeyIndex = path.length - 1;
  for (var i = 0; i < lastKeyIndex; ++i) {
    let key = path[i];
    if (!(key in final)) {
      final[key] = /^\d+$/.test(path[i + 1]) ? [] : {};
    }
    final = final[key];
  }
  final[path[lastKeyIndex]] = value;
}

console.log(unflatten(flattened))
.as-console-wrapper { min-height: 100vh; }


0
你可以遍历键并将字符串拆分为单个属性。要构建一个新对象,你可以检查数字,并为这些属性采用数组。

function setValue(object, path, value) {
    var way = path.split('.'),
        last = way.pop();

    way.reduce(function (o, k, i, kk) {
        return o[k] = o[k] || (isFinite(i + 1 in kk ? kk[i + 1] : last) ? [] : {});
    }, object)[last] = value;
}

function unFlatten(object) {
    var keys = Object.keys(object),
        result = isFinite(keys[0][0]) ? [] : {};
    keys.forEach(function (k) {
        setValue(result, k, object[k]);
    });
    return result;
}

console.log(unFlatten({
    'a': 1,
    'b.0.c': 2,
    'b.1.c': 3
}));
console.log(unFlatten({
    '0': 1,
    '1.0.c': 2,
    '1.1.c': 3
}));
.as-console-wrapper { max-height: 100% !important; top: 0; }


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接