1

I have an array:

array = {
  "data": [
    { "value": [ 100, 13, 16 ] },
    { "value": [ 101, 14, 17 ] },
    { "value": [  12, 15, 18 ] }
  ]
}

Which I am reformatting into a new array of just the columns:

const columnArray = jsonData.map( (current, index, arr) => {
  let out = [];
  for( let i = 0; i < current.value.length; i++ ) {
    out.push( arr[ i ].value[ index ] );
  }
  return out;
});

// output
[
  [ 100, 101, 12 ],
  [  13,  14, 15 ],
  [  16,  17, 18 ]
]

How would I re-write the columnArray mapping to do the column array and be able to sum from the previous value?

So the intended output from the original array would be:

[
  [ 100, 201, 213 ],
  [  13,  27,  42 ],
  [  16,  33,  51 ]
]

I would also like the summing to be scalable (though it will always be in a 1:1 ratio). So if the data has 20 items, then each value will have 20 integers in that array too.

I have tried looping through but that didn't work as I only sum from the previous, not all the previous. And this wouldn't scale either:

const columnArray = jsonData.map( (current, index, arr) => {
  let out = [];

  for( let i = 0; i < current.value.length; i++ ) {
    // dont touch first
    if( i < 1 ) {
      out.push( arr[ i ].value[ index ] );
    } else {
      out.push( arr[ i ].value[ index ] + arr[ i - 1 ].value[ index ] )
    }
  }
  return out;
});
markb
  • 1,100
  • 1
  • 15
  • 40
  • This is called a [cumulative sum](https://stackoverflow.com/questions/20477177/creating-an-array-of-cumulative-sum-in-javascript) which is applied to each array individually -- the fact that it's a 2d array isn't important because you can just add a `map` call to the linked answer. – ggorlen May 13 '21 at 01:05

3 Answers3

3

Instead of pushing the array element, add it to a variable accumulating the running totals, and push that.

const jsonData = [{
    "value": [100, 13, 16]
  },
  {
    "value": [101, 14, 17]
  },
  {
    "value": [12, 15, 18]
  }
];

const columnArray = jsonData.map((current, index, arr) => {
  let out = [];
  let total = 0;
  for (let i = 0; i < current.value.length; i++) {
    total += arr[i].value[index]
    out.push(total);
  }
  return out;
});

console.log(columnArray);

or with a nested map():

const jsonData = [{
    "value": [100, 13, 16]
  },
  {
    "value": [101, 14, 17]
  },
  {
    "value": [12, 15, 18]
  }
];

const columnArray = jsonData.map((current, index, arr) => {
  let total = 0;
  return arr.map(el => total += el.value[index])
});

console.log(columnArray);
Barmar
  • 741,623
  • 53
  • 500
  • 612
0

You're thinking this in the wrong way. You're storing the sum in the list, not anywhere else. So even tho your index is increasing, the resulting sum resides in the list, so to achieve your goal you have to save it in some variable then push the variable into the final list. Follow this code below:

const columnArray = array.data.map((current, index, arr) => {
  let out = [];
  let temp;
  for (let i = 0; i < current.value.length; i++) {
    // dont touch first
    if (i < 1) {
      temp = arr[i].value[index];
      out.push(arr[i].value[index]);
    } else {
      temp = arr[i].value[index] + temp;
      out.push(temp);
    }
  }
  return out;
});


Sifat Amin
  • 1,091
  • 6
  • 15
0

something like that...

const array0 = {
  "data": [
    { "value": [ 100, 13, 16 ] },
    { "value": [ 101, 14, 17 ] },
    { "value": [  12, 15, 18 ] }
  ]
}

const 
  rowCount  = array0.data.reduce((c,{value})=>Math.max(c,value.length) ,0) 
, arrResult = Array(rowCount).fill(0).map(x=>Array(array0.data.length).fill(0))
;
arrResult.forEach((_,i,arr)=>
  {
  array0.data[i].value.forEach((v,j)=>
    {
    arr[j][i] = v + (i? arr[j][i-1] : 0 )
    })
  })

console.log( arrResult)
.as-console-wrapper {max-height: 100%!important;top:0}
Mister Jojo
  • 20,093
  • 6
  • 21
  • 40