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\$
3
  • 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\$ Mar 14, 2020 at 22:34
  • \$\begingroup\$ sorry, i changed some var names and missed that one. fixed \$\endgroup\$
    – Erich
    Mar 14, 2020 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\$ Mar 14, 2020 at 22:43

1 Answer 1

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];
    }
}
\$\endgroup\$
1
  • \$\begingroup\$ i was definitely overthinking this problem. thanks for the help! \$\endgroup\$
    – Erich
    Mar 14, 2020 at 23:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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