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;
});
1
  • This is called a cumulative sum 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. Commented May 13, 2021 at 1:05

3 Answers 3

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

Sign up to request clarification or add additional context in comments.

1 Comment

that nested map is very clean - thank you
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;
});


Comments

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}

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.