momentum
momentum

Reputation: 13

How to sum property in array of objects, based on a condition

I'm a junior Web Developer, looking for some guidance solving a problem. Please excuse me if I'm missing anything integral, as this my first time posting here.

I have an array of some data returned like so:

[
 {x: Date(1234), y: 0}
 {x: Date(1235), y: 0}
 {x: Date(1236), y: 300}
 {x: Date(1237), y: 300}
 {x: Date(1238), y: 300}
 {x: Date(1239), y: 300}
 {x: Date(1240), y: 300}
 {x: Date(1241), y: 0}
 {x: Date(1242), y: 0}
 {x: Date(1243), y: 0}
]

If possible, I'd like to return a new array in which all consecutive 'y' values > 0 are summed. In the new array, the summed value should be associated with the first 'x' value of the summed items, like so:

[
 {x: Date(1234), y: 0}
 {x: Date(1235), y: 0}
 {x: Date(1236), y: 1500}
 {x: Date(1241), y: 0}
 {x: Date(1242), y: 0}
 {x: Date(1243), y: 0}
]

I'm thinking this will likely involve 'reduce,' but I'm a little unsure how to proceed. Any help would be greatly appreciated.

Thanks in advance!

Upvotes: 1

Views: 2284

Answers (3)

D. Seah
D. Seah

Reputation: 4592

I think you can use a reduce function like this.

var arr = [{
    x: Date(1234),
    y: 0
  },
  {
    x: Date(1235),
    y: 0
  },
  {
    x: Date(1236),
    y: 300
  },
  {
    x: Date(1237),
    y: 300
  },
  {
    x: Date(1238),
    y: 300
  },
  {
    x: Date(1239),
    y: 300
  },
  {
    x: Date(1240),
    y: 300
  },
  {
    x: Date(1241),
    y: 0
  },
  {
    x: Date(1242),
    y: 0
  },
  {
    x: Date(1243),
    y: 0
  }
];

var yGreaterThanZero = null;
var aggregated = arr.reduce(function(acc, cur) {
  if (cur.y > 0) {
    if (!yGreaterThanZero) {
      acc.push(cur);
      yGreaterThanZero = cur;
    } else {
      yGreaterThanZero.y += cur.y;
    }
  } else {
    acc.push(cur);
  }
  return acc;
}, []);

console.log(aggregated);

Upvotes: 1

K.F
K.F

Reputation: 469

Using reduce, you could do something like this: https://jsbin.com/leladakiza/edit?js,console

var input = [
 {x: Date(1234), y: 0},
 {x: Date(1235), y: 0},
 {x: Date(1236), y: 300},
 {x: Date(1237), y: 300},
 {x: Date(1238), y: 300},
 {x: Date(1239), y: 300},
 {x: Date(1240), y: 300},
 {x: Date(1241), y: 0},
 {x: Date(1242), y: 0},
 {x: Date(1243), y: 0},
];

var output = input.reduce(function (acc, val) {
  var lastIndex = acc.length - 1;
  if (val.y <= 0 || lastIndex < 0 || acc[lastIndex].y <= 0) {
    acc.push(val);
  } else {
    acc[lastIndex].y += val.y;
  }
  return acc;
}, []);

Upvotes: 2

Prasanna
Prasanna

Reputation: 4656

This is a very crude logic. We start recording when a value greater than 0 is obtained and push it at the end of the recording (value less than 0)

var a = [
 {x: Date(1234), y: 0},
 {x: Date(1235), y: 0},
 {x: Date(1236), y: 300},
 {x: Date(1237), y: 300},
 {x: Date(1238), y: 300},
 {x: Date(1239), y: 300},
 {x: Date(1240), y: 300},
 {x: Date(1241), y: 0},
 {x: Date(1242), y: 0},
 {x: Date(1243), y: 0},
 {x: Date(1244), y: 200},
 {x: Date(1245), y: 200},
 {x: Date(1246), y: 200},
 {x: Date(1247), y: 200},
]

var newA = [];
var recording = false;
var temp = {}
a.forEach(item => {
  if (item.y > 0) {
    recording = true;
    if (temp.y) {
      if(!temp.x) temp.x = item.x;
      temp.y = temp.y + item.y
    } else {
      temp = item;
    }
  } else {
    if (recording) newA.push(temp)
    recording = false;
    temp = {};
    newA.push(item);
  }
})
if (recording) newA.push(temp)

console.log(newA)

Upvotes: 0

Related Questions