zilj
zilj

Reputation: 629

How can I sum common keys in an array of objects?

I have a pretty tricky data structure that I need to iterate over in order to produce a more concise object.

In lodash (or javascript if better), is there a way to generate unique key values by taking all original.day types and adding their original.value together, then merging into their given sets to create a new object;

Here is my original object, some items appear as duplicates but the values should still be added together to their corresponding day.

var original = [

  { day: 01, value: 0 },
  { day: 01, value: 2 },

  { day: 02, value: 4 },
  { day: 02, value: 1 },

  { day: 03, value: 3 },
  { day: 03, value: 9 },

  { day: 01, value: 0 },
  { day: 01, value: 4 },

  { day: 02, value: 2 },
  { day: 02, value: 0 },

  { day: 03, value: 3 },
  { day: 03, value: 3 }

];

I then need to get the following:

var output = [
  { day01: 6 },
  { day02: 7 },
  { day03: 18 }
];

or :

var output = [
  [01,6],
  [02,7],
  [03,18]
];

I have tried many different approaches with lodash (uniq,reduce,each etc...) with no joy, perhaps I'm not using the right method. Any help greatly appreciated.

Upvotes: 0

Views: 959

Answers (3)

Ori Drori
Ori Drori

Reputation: 191936

This will give you the 2nd format [["01",6], ["02",7], ["03",18]]:

_.pairs(_.reduce(original, function(output, item) {
    var day = '0' + item.day;
    output[day] = (output[day] || 0) + item.value;
    return output;
}, {}));

Upvotes: 0

ryeballar
ryeballar

Reputation: 30088

The quickest way to go around with this is by using _.reduce for lodash or Array.prototype.reduce() for plain javascript.

Lodash

DEMO

function getTotalDays(collection) {
  return _.reduce(collection, function(result, item) {
    var index = 'day' + _.padLeft(item.day, 2, 0);
    result[index] = (result[index] || 0) + item.value;
    return result;
  }, {});
}

PLAIN JAVASCRIPT

DEMO

function getTotalDays(collection) {
  return collection.reduce(function(result, item) {
    var index = 'day' + (item.day < 10? '0': '') + item.day;
    result[index] = (result[index] || 0) + item.value;
    return result;
  }, {});
}

Upvotes: 1

jfriend00
jfriend00

Reputation: 707158

You can do it like this in plain Javascript. The creation of the day01 style keys just takes a couple extra lines of code. You can run this snippet here to see the result:

function sumDays(list) {
    var result = {};
    list.forEach(function(item) {
        var dayNum = item.day;
        var dayPrefix = dayNum <= 9 ? "0" : "";
        var key = "day" + dayPrefix + dayNum;
        if (!result[key]) {
            result[key] = 0;
        }
        result[key] += item.value;
    });
    return result;
}

var original = [

  { day: 01, value: 0 },
  { day: 01, value: 2 },

  { day: 02, value: 4 },
  { day: 02, value: 1 },

  { day: 03, value: 3 },
  { day: 03, value: 9 },

  { day: 01, value: 0 },
  { day: 01, value: 4 },

  { day: 02, value: 2 },
  { day: 02, value: 0 },

  { day: 03, value: 3 },
  { day: 03, value: 3 }

];

var r = sumDays(original);
document.write(JSON.stringify(r));

Upvotes: 1

Related Questions