Map减少性能较差的javascript数组对象

时间:2017-05-10 19:26:36

标签: javascript ecmascript-6 lodash

我正在尝试对某些javascript对象进行一些映射/缩减,并且失败了。

来自后端的数据看起来像这样:

[
  {table:"a1", data: {colA:1,colB:2,colC:3}},
  {table:"a2", data: {colA:2,colB:3,colC:4}},
  {table:"a3", data: {colA:3,colB:4,colC:5}}
]

Recharts需要以下格式的数据(将源数据键作为结果的唯一“名称”键)

[
  {name: 'colA', a1: 1, a2: 2, a3: 3},
  {name: 'colB', a1: 2, a2: 3, a3: 4},
  {name: 'colC', a1: 3, a2: 4, a3: 5}
]

我当前的解决方案目前是O(n^n),因为我正在构建一个结果对象,并且每次都循环遍历它。我正在使用ECMA6 / Babel以及Lodash。任何指导将不胜感激!谢谢!

编辑:这是我目前的解决方案

var dest = []
Lodash.forEach(source,(o) => {
  var table = o.table;
  Lodash.forEach(o.data, (p,q) => {
    // See if the element is in the array
    const index = Lodash.findIndex(dest,(a) => {return a.name === q});
    if ( index === -1) {
      var obj = {};
      obj[table] = Number(p);
      obj.name = q;
      dest.push(obj);
    } else {
      dest[index][table] = Number(p);
    }
  })
});

2 个答案:

答案 0 :(得分:1)

首先,算法的速度实际上是O(n ^ n ^ n),因为你有3个嵌套循环。我简化它的方法是首先使用一个对象,然后从该对象创建一个数组。像这样:



NULL




这将消除循环结果数组以添加到对象的需要。在迭代输入数组及其数据时仍然有O(n ^ m)+ O(l)条件,但是通过迭代结果,你不会有更复杂的速度条件每次迭代都有数组。

此函数还可以处理每个表的数据可能不同的实例。例如,你可能在其中一个条目中有colA和colB而不是colC。或者你可能在另一个条目上有一个colD。

答案 1 :(得分:1)

如果使用地图跟踪最终列,则可以大规模简化此操作。通过将它们存储在地图中,您可以获得持续查找时间的好处。

如果我们说表的数量为N且列数为M,那么您将获得O(N * M)。



let input = [
  { table: "a1", data: { colA: 1, colB: 2, colC: 3 } },
  { table: "a2", data: { colA: 2, colB: 3, colC: 4 } },
  { table: "a3", data: { colA: 3, colB: 4, colC: 5 } }
];

let desiredOutput = [
  { name: 'colA', a1: 1, a2: 2, a3: 3 },
  { name: 'colB', a1: 2, a2: 3, a3: 4 },
  { name: 'colC', a1: 3, a2: 4, a3: 5 }
];

let keys = null;
let map = null;

input.forEach(row => {
  if (map === null) {
    // Cache the column names
    keys = Object.keys(row.data);
    
    // Generates objects such a `{ name: 'colA' }`
    // and stores them at a key of 'colA'
    map = keys
      .reduce((o, k) => (o[k] = {
        name: k
      }, o), {});
  }

  // For each column ('colA', 'colB', etc.)
  keys.forEach(key => {
    // Create a new property for the table name
    // ('a1', 'a2', etc.)
    // and copy the matching column value from the input
    map[key][row.table] = row.data[key];
  });
});

// Convert the map to an array of just the values
let output = Object.values(map);
console.log(JSON.stringify(output) === JSON.stringify(desiredOutput));
console.log(output);