如何将[{id:1,var1:val1,var2:val2,varX:[time1,time2,time3]}]调和为[{id:1,var1:val1,var2:val2,varX1:time1,varX2:time2 ,varX3:time3}]

时间:2020-04-13 04:15:45

标签: javascript

我正在标题上显示的数据格式转换中工作,但我不知道如何弄清楚。我尝试编写打击代码以添加第二维数组的变量名称:

const data = [
  { id: 1, var1: 'val1', var2: 'val2', varX: ['time1', 'time2', 'time3'] },
  { id: 2, var1: 'val2', var2: 'val3', varX: ['time4', 'time5', 'time6'] },
];

const test = data.map((o) => o.varX);

for (i = 0; i < test.length; i++) {
  const test2 = test[i].reduce((res, cur, idx) => {
    res[`varX${idx}`] = cur;
    return res;
  }, {});
  console.log(test2);
}

但是我期望的结果应该是:

[{id:1, var1:val1, var2:val2, varX1:time1, varX2:time2, varX3:time3},{id:2, var1:val2, var2:val3, varX1:time4, varX2:time5, varX3:time6}]

有人可以指导我如何转换数据吗?

3 个答案:

答案 0 :(得分:0)

由于test中的第一个映射,您仅对varX的值进行操作。您只需添加其他操作即可将原始data[i]对象与新的缩小的varX对象合并。

const data = [
  { id: 1, var1: 'val1', var2: 'val2', varX: ['time1', 'time2', 'time3'] },
  { id: 2, var1: 'val2', var2: 'val3', varX: ['time4', 'time5', 'time6'] },
];

const test = data.map((o) => o.varX);

for (i = 0; i < test.length; i++) {
  const test2 = test[i].reduce((res, cur, idx) => {
    res[`varX${idx}`] = cur;
    return res;
  }, {});
  // exclude varX and merge your new varX${i} back into data[i]
  const {varX, ...test3} = Object.assign(data[i], test2);
  console.log(test3);
}

转换就地代码。我故意避免使用reduce,因为语法变得不易理解,并且增加了性能开销。缺点是此代码使原始data发生突变(就地转换数据)。通过在映射时创建对象val的副本,可以轻松缓解这种情况。

[1,2,3,4,5,6].forEach( i => eval(`time${i} = "time${i}";val${i} = "val${i}"`) );

const data = [{id:1, var1:val1, var2:val2, varX:[time1, time2, time3]}, {id:2, var1:val2, var2:val3, varX:[time4, time5, time6]}]

data.forEach((val, i)=>{
  val.varX.forEach( (X,i) => val[`varX${i}`]=X );
  delete val.varX;
  console.log(val);
  return val;
});
console.log(data);

我在下面使用reduce和spread语法创建了一个版本。您可以将传播语法视为将属性复制到正在生成的新对象的简单操作。我已使用解构语法将varX与其余属性隔离,并将它们放在varXnoVarX中。

这还具有深度复制的优点,除了数据中最终外部引用的对象之外。

  [1,2,3,4,5,6].forEach( i => eval(`time${i} = "time${i}";val${i} = "val${i}"`) );

  const data = [{id:1, var1:val1, var2:val2, varX:[time1, time2, time3]}, {id:2, var1:val2, var2:val3, varX:[time4, time5, time6]}]
  const expanded = data.map(val => {
    const {varX, ...noVarX} = val;
    return {
      ...noVarX,
      ...varX.reduce( (res, cur, idx) => 
          ({ ...res, [`varX${idx}`]: cur }), {})
    };
  });
  console.log(expanded);

答案 1 :(得分:0)

您的代码存在的问题是,通过仅映射具有varX的值,您会从data中引出不是varX的属性。然后,您可以很好地减少它们,但是您必须将“剩余”属性合并到新对象中,这对我来说有点麻烦。相反,您可以执行以下操作:

const data = [
  { id: 1, var1: "val1", var2: "val2", varX: ["time1", "time2", "time3"] },
  { id: 2, var1: "val2", var2: "val3", varX: ["time4", "time5", "time6"] },
];

const test = data.map((o) => {
  return Object.entries(o).reduce((p, [k, v]) => {
    if (k === "varX") {
      for (let index = 0; index < v.length; index++) {
        p[`varX${index + 1}`] = v[index];
      }
    } else {
      p[k] = v;
    }
    return p;
  }, {});
});

console.log(test);

首先,您映射数据对象,然后为每个对象减少其键/值对,并检查属性是否为varX,如果是,则遍历数组并将其分配给新对象。 varX${index + 1},因为您希望第一个属性为varX1,否则您只需保留相同的键/值对。

答案 2 :(得分:0)

在使用第二种reduce方法将varX替换为新对象之后,您需要在map()方法而不是数组中创建对象

const data = [{'id':1, 'var1':'val1', 'var2':'val2', 'varX':['time1', 'time2', 'time3']}, 
            {'id':2, 'var1':'val2', 'var2':'val3', 'varX':['time4', 'time5', 'time6']}]

const test = data.map(item => item.varX);
const test2 = {}
for (i = 0; i < test.length; i++) {
            test2[i] = test[i].reduce((accum, item, index) => {
              return { ...accum, [`varX${index}`]: item};
            }, {});
          }

const dataX = data.map((item, index) => {
  delete item.varX
  return { ...item, ...test2[index] }
});
 
console.log(dataX)