1
\$\begingroup\$

I have an array of objects, each with a dimensions field for storing various metrics related to the object, e.g. length, width, weight, etc. Each object may be different in terms of what metrics it has.

I have a solution but not sure if it's optimal.

let dimensions = [{ a: 1, b: 2, c: 3}, { a: 2, c: 1, d: 3 }, { b: 1, e: 8, f: 1 }]

// get all keys
let dimensionsFields = _.map(dimensions, Object.keys);
// => [[a, b, c], [a, c, d], [b, e, f]]

// flatten
dimensionsFields  = _.flatten(dimensionsFields );
// => [a, b, c, a, c, d, b, e, f]

// filter out duplicates
dimensionsFields  = _.uniq(dimensionsFields );
// => [a, b, c, d, e, f]

// init return data
let dimensionsData = {};

// loop through available metrics, add up the values
dimensionsFields.forEach(field => {
  dimensionsData[field] = _.reduce(dimensions, function(a, b) {
    return a + b[field];
  }, 0);
});
// => { a: 3, b: 3, c: 4, d: 3, e: 8, f: 1 }
\$\endgroup\$
  • 1
    \$\begingroup\$ As written your code doesn't run, I imagine _ is lodash, but metrics isn't defined (I guess it should be dimensions), but then this still doesn't work for me. \$\endgroup\$ – Countingstuff Mar 14 at 22:34
  • \$\begingroup\$ sorry, i changed some var names and missed that one. fixed \$\endgroup\$ – Erich Mar 14 at 22:37
  • 1
    \$\begingroup\$ It still doesn't work for me, I get that every key has value NaN, which isn't too surprising since for instance we do a + b["d"] but d might not be a property of b. \$\endgroup\$ – Countingstuff Mar 14 at 22:43
2
\$\begingroup\$

What do you mean optimal?

Your thing transforms the object lots of times, which is liable to not be very efficient, if that's what you meant.

Here's something that I hope is simple to read that does your task.

function sumObjects(obj1, obj2) {
    return Object.keys(obj2).reduce(
        (acc, currKey) => ({
        ...acc,
        [currKey]: acc[currKey] ? acc[currKey] + obj2[currKey] : obj2[currKey]
        }),
        obj1
    );
}

const result = dimensions.reduce(sumObjects);

The observation is that you just need to see how to do your task for two objects and the rest is just a reduce.

The most efficient thing will likely be just a for loop, like

const res = {};
for (const obj of dimensions) {
    for (const key in obj) {
        res[key] = res[key] ? res[key] + obj[key] : obj[key];
    }
}
| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ i was definitely overthinking this problem. thanks for the help! \$\endgroup\$ – Erich Mar 14 at 23:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.