0

i have an array with the following format

[
[{year:2015, value:23000, value1:1000},{year:2016,value:1000, value1:2000},{year:2017,value:400, value1:3000}],
[{year:2015, value:10000, value1:1000},{year:2016,value:2000, value1:3000},{year:2017,value:500, value1:2000}],
]

i want to sum them together, in this example, i want to have

[{year:2015,value:33000, value1:2000},{year:2016,value:3000, value1:5000},{year:2017,value:900, value1:5000}]

if there are only two arrays in the array but there maybe more arrays in the bigger array. how can i achieve this? currently, i am not able to figure out a good method. Thanks

2
  • Are there only two only two levels of arrays, or can inner arrays have arrays in them as well? Commented Apr 29, 2017 at 13:47
  • hi only two levels Commented Apr 29, 2017 at 13:53

4 Answers 4

2

Ecmascript5 solution:

var arr = [
        [{year:2015, value:23000, value1:1000},{year:2016,value:1000, value1:2000},{year:2017,value:400, value1:3000}],
        [{year:2015, value:10000, value1:1000},{year:2016,value:2000, value1:3000},{year:2017,value:500, value1:2000}]
    ],
    
    // summing up values for each `year`
    years = arr.reduce(function (r, a) {
        a.forEach(function (o) {
            y = o.year;
            if (Array.isArray(r[y])) {
                r[y][0] += o.value;
                r[y][1] += o.value1;
            } else {
                r[y] = [o.value, o.value1];
            }
        });
        return r;
    }, {}),

    // constructing the resulting array containing objects with `year` totals
    result = Object.keys(years).map(function (y) {
        return {year: y, value: years[y][0], value1: years[y][1]};
    });

console.log(result);

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

4 Comments

actually, there are more properties inside the objects, i tested in that case, this solution failed to work.[{year:2015, value:23000, value1:1000},{year:2016,value:1000, value:200},{year:2017,value:400, value1:600}],
@onegun, you didn't mention that in your question and you didn't post the extended input array
yes, i was looking for a general solution, thought that cause the confusion, i will edit that
@onegun, even though you have changed your initial condition, I've updated my answer. See the update
1

You can loop over the items and add value agains a year number (key) in a map / object.

var data = [
[{year:2015, value:23000},{year:2016,value:1000},{year:2017,value:400}],
[{year:2015, value:10000},{year:2016,value:2000},{year:2017,value:500}],
];

var output = {};

data.forEach(function(item) {
  item.forEach(function(obj) {
    output[obj.year] = (output[obj.year] || 0) + obj.value;
  });
});
output = [output]

console.log(output);

One way is to flat this 2D array first.

var output = {};
var flatArray = data.reduce(function(a, b) {
  return a.concat(b);
}, []);

flatArray.forEach(function(obj) {
  output[obj.year] = (output[obj.year] || 0) + obj.value;
});

output = [output]
console.log(output);

output: [{ 2015: 33000, 2016: 3000, 2017: 900 }]

5 Comments

Your output doesn't match his: [{year:2015,value:33000},{year:2016,value:3000},{year:2017,value:900}] where his is an array of objects and yours is an array of one object.
@ThisClark outer array does not make sense but I've update my code to match the exact same output.
actually, there are more properties inside the objects, i tested in that case, this solution failed to work.[{year:2015, value:23000, value1:1000},{year:2016,value:1000, value:200},{year:2017,value:400, value1:600}], that is why i want that kind of output
@onegun An object can't have two keys with same name. {year:2016,value:1000, value:200} . Also you did not mentioned this in your question
hi i have updated the question, they are not same name properties, but one is value another is value1 used in the example
1

You could use a hash table for collecting a single year and a nested approach for the arrays with iterating all properties of the given objects.

Then create new properties and add the actual value.

It works with an arbitrary count of properties.

var data = [[{ year: 2015, value: 23000, value1: 1000 }, { year: 2016, value: 1000, value1: 2000 }, { year: 2017, value: 400, value1: 3000 }], [{ year: 2015, value: 10000, value1: 1000 }, { year: 2016, value: 2000, value1: 3000 }, { year: 2017, value: 500, value1: 2000 }]],
    result = data.reduce(function (hash) {
        return function (r, a) {
            a.forEach(function (o) {
                if (!hash[o.year]) {
                    hash[o.year] = { year: o.year };
                    r.push(hash[o.year]);
                }
                Object.keys(o).forEach(function (k) {
                    if (k !== 'year') {
                        hash[o.year][k] = (hash[o.year][k] || 0) + o[k];
                    }
                });
            });
            return r;
        };
    }(Object.create(null)), []);

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Comments

0

Here's a working solution. This will do what you're looking for. Hope it helps!

var arr =   [
      [{year:2015, value:23000, value1:1000},{year:2016,value:1000, value1:2000},{year:2017,value:400, value1:3000}],
          [{year:2015, value:10000, value1:1000},{year:2016,value:2000, value1:3000},{year:2017,value:500, value1:2000}],
      ]

var result = [];

  for(var i = 0; i < arr[0].length; i++){
      var count = 0
      var count2 = 0;
      for(var j = 0; j < arr.length; j++){
       var year = arr[j][i].year;
       count  += arr[j][i].value;
       count2 += arr[j][i].value1;
      }
      result.push({
          year: year,
          value: count,
          value1: count2
      });
  }
  console.log(result);

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.