Home > Back-end >  Javascript nested array: halve items and sum them up
Javascript nested array: halve items and sum them up

Time:12-03

I'm trying to create a function which returns me halve the data sumed up. I was able to do it on a non-nested Array but failing on the nested Array. I get the error Cannot read properties of undefined (reading 'push').

How the returned data should look like:

var data = [{"Key":1,"values":[
{"LastOnline":"21-11-29","Value":2},
{"LastOnline":"21-12-01","Value":2},
{"LastOnline":"21-12-03","Value":2}
]}];

What I have right now:

var data = [{"Key":1,"values":[
{"LastOnline":"21-11-28","Value":1},
{"LastOnline":"21-11-29","Value":1},
{"LastOnline":"21-11-30","Value":1},
{"LastOnline":"21-12-01","Value":1},
{"LastOnline":"21-12-02","Value":1},
{"LastOnline":"21-12-03","Value":1},
]}];

  function halveMonth(data){
    var newData = [];
    var temp = [{"key":data.key,"values":[{}]}];
    // sum 2 togheter
    for(var i=1;i<data.values.length;i  ){
      if(data.values[i]){
        temp.values[i].push({"LastOnline":data.values[i].LastOnline, "Value":(data.values[i].Value   data.values[[i-1]].Value)});
      }
    }
    for(var i=0;i<temp.values.length;i  ){
      if(i % 2 == 0){
        newData.push(temp.values[i]);
      }
    }
    return newData;
  }
  
  console.log(halveMonth(data));
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

CodePudding user response:

The variable data you declare at the first line of your snippet is an array. So you can't do data.values. You first need to indicate which index of your array you want to read. In this case : data[0].values

CodePudding user response:

First things first, you data is itself an array - so assuming your real data has more than 1 element you'll need to do the same thing for each one.

It's helpful to start off with a method which does the work on just 1 element

const justASingle = {"Key":1,"values":[{"LastOnline":"21-11-28","Value":1},{"LastOnline":"21-11-29","Value":1},{"LastOnline":"21-11-30","Value":1},{"LastOnline":"21-12-01","Value":1},{"LastOnline":"21-12-02","Value":1},{"LastOnline":"21-12-03","Value":1}]};

function halveMonthSingle(data) {

  return {
    ...data,
    values: data.values.reduce((acc, item, idx) => {
      if ((idx % 2) != 0)
        acc.push({
          ...item,
          Value: data.values[idx - 1].Value   item.Value
        })
      return acc;
    }, [])
  }
}

console.log(halveMonthSingle(justASingle))
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

Once you have that you can just use map do do it for every element

const data = [{"Key":1,"values":[{"LastOnline":"21-11-28","Value":1},{"LastOnline":"21-11-29","Value":1},{"LastOnline":"21-11-30","Value":1},{"LastOnline":"21-12-01","Value":1},{"LastOnline":"21-12-02","Value":1},{"LastOnline":"21-12-03","Value":1}]}];

function halveMonthSingle(data) {

  return {
    ...data,
    values: data.values.reduce((acc, item, idx) => {
      if ((idx % 2) != 0)
        acc.push({
          ...item,
          Value: data.values[idx - 1].Value   item.Value
        })
      return acc;
    }, [])
  }
}

const result = data.map(halveMonthSingle)

console.log(result)
<iframe name="sif3" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

CodePudding user response:

I would use reduce - saves me from trying to figure out why your two loops do not work other than data.values should be data[0].values

var data = [{"Key":1,"values":[{"LastOnline":"21-11-28","Value":1},{"LastOnline":"21-11-29","Value":1},{"LastOnline":"21-11-30","Value":1},{"LastOnline":"21-12-01","Value":1},{"LastOnline":"21-12-02","Value":1},{"LastOnline":"21-12-03","Value":1},]}];

const newArr = data.slice(0); // to not mutate original
newArr[0].values = data[0].values.reduce((acc,item,i) => { 
  if (i%2 !== 0) { // every second
    acc.push(data[0].values[i]); // push the item
    acc[acc.length-1].Value  = data[0].values[i-1].Value; // add the first
  }
  return acc
},[])

console.log(newArr)
<iframe name="sif4" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

CodePudding user response:

JS variables are case sensitive. Keep the key consistent everywhere. If you don't plan to use reduce here is the solution.

var data = [{"key":1,"values":[
{"LastOnline":"21-11-28","Value":1},
{"LastOnline":"21-11-29","Value":1},
{"LastOnline":"21-11-30","Value":1},
{"LastOnline":"21-12-01","Value":1},
{"LastOnline":"21-12-02","Value":1},
{"LastOnline":"21-12-03","Value":1},
]}];

function halveMonth(data){
let newData = []
for (let i = 0; i < data.length; i  ) {
    let temp = {"key":data[i].key,"values":[]}
    for (let j = 0; j < data[i].values.length; j  = 2) {
        const res = (j 1===data[i].values.length) ? data[i].values[j].Value : data[i].values[j].Value   data[i].values[j 1].Value
        temp.values.push({"LastOnline":(j 1===data[i].values.length)?data[i].values[j].LastOnline:data[i].values[j 1].LastOnline,"Value":res});
    }
    newData.push(temp);
}
return newData
}
  
  console.log(halveMonth(data));
<iframe name="sif5" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

  • Related