简体   繁体   English

Map Reduce跨性能差的对象的javascript数组

[英]Map Reduce across javascript array of objects with poor performance

I'm trying to do some mapping/reducing on some javascript object and failing miserably. 我正在尝试对某些javascript对象进行一些映射/减少操作,并且失败了。

The data as it comes from the backend comes in looking something like this: 来自后端的数据看起来像这样:

[
  {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 needs the data in the following format (make the source data keys as the unique "name" key for the result) 图表需要以下格式的数据(将源数据键作为结果的唯一“名称”键)

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

My current solution is currently O(n^n) because I'm building an result object, and looping over it every time. 我当前的解决方案当前为O(n^n)因为我正在构建一个结果对象,并每次对其进行循环。 I'm using ECMA6/Babel as well as Lodash. 我正在使用ECMA6 / Babel以及Lodash。 Any guidance would be greatly appreciated! 任何指导将不胜感激! Thanks! 谢谢!

Edit: Here's my current solution 编辑:这是我当前的解决方案

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

To start, the speed of your algorithm is actually O(n^n^n) because you have 3 loops nested. 首先,您的算法速度实际上是O(n ^ n ^ n),因为您嵌套了3个循环。 The way I would simplify it is to use an object first, and then create an array from the object. 我要简化的方法是先使用一个对象,然后从该对象创建一个数组。 Like so: 像这样:

 function convert(original) { var tmp = {}; for(var tableIndex in original) { var tableObj = original[tableIndex]; for(var colKey in tableObj.data) { var col = tableObj.data[colKey]; if(tmp[colKey] === undefined) { tmp[colKey] = {name: colKey}; } tmp[colKey][tableObj.table] = col } } var output = []; for(var index in tmp) { output.push(tmp[index]); } return output; } var original = [ {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}} ] console.log(convert(original)); 

This will eliminate the need to loop over the result array to add to the objects. 这样就无需遍历结果数组以添加到对象中。 You still have a O(n^m) + O(l) condition when iterating over the input array and it's data, but you don't have an even more complex speed condition by also iterating over the result array on every iteration as well. 在输入数组及其数据上进行迭代时,您仍然具有O(n ^ m)+ O(l)条件,但是在每次迭代时也对结果数组进行迭代,就没有更复杂的速度条件。

This function can also handle instances where your data might be different per table. 此功能还可以处理每个表的数据可能不同的实例。 So you may have colA and colB but not colC in one of the entries, for example. 因此,例如,您可能在其中一项中有colA和colB但没有colC。 Or you may have a colD on another entry. 或者您可能在另一个条目上输入了colD。

You can massively simplify this if you use a map to track the eventual columns. 如果使用地图跟踪最终的列,则可以大大简化此过程。 By storing them in a map as you go, you gain the benefit of constant lookup time. 通过随时将它们存储在地图中,您可以获得不断查找时间的好处。

If we say that the number of tables is N and the number of columns is M then you'll get O(N*M). 如果我们说表的数量是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); 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM