There are several other good answers to your question, though I'd argue that this one is shorter, faster, and simpler to understand. (Look at the bottom of my solution for the working example). We can achieve this using a few simple array and object methods.
1. Consolidating the data
First, we'll consolidate each of your nested arrays of objects into single objects, with the categories (our unique values) as the keys, and their values. We can do this using the array reduce() method. Here we'll be using {} as our accumulator's initial value and then push to that accumulator object by setting its properties. As we iterate through, we'll add each value to the associated category property. This can cause errors if the property is not yet set on the accumulator object.
One way of working around this would be to use a ternary to check whether the property exists yet, and then either set the property if one doesn't yet exist, or add to the value if it does, like this:
// a is the accumulator, c is our category name, and v is our value
a[c] ? a[c] += parseFloat(v) : a[c] = parseFloat(v) // -> {a: 66, b: 46, c: 61}
A simpler way to do this is with nullish coalescing. Nullish coalescing will check to see if the value is null or undefined and if so, we use 0 as the current value. In this method, we are always setting property, and just overwriting it with itself (or 0) added to the current value being evaluated, like this:
a[c] = (a[c] ?? 0) + parseFloat(v) // -> {a: 66, b: 46, c: 61}
I also opted to use object restructuring when setting the parameter names in my reduce method to have all three variables easily accessible to me. This is not required though, so either of the below methods would work just the same. Using object destructuring also allows us to rename our destructured parameters to easier use (c, v instead of category, value). To learn more about destructuring and renaming parameters, check out Wes Bos's post, Rename & Destructure Variables in ES6.
// Without Object Destructuring
arr.reduce((a, o) => (a[o.category] = (a[o.category] ?? 0) + parseFloat(o.value), a), {});
// With Object Destructuring
arr.reduce((a, {value: v, category: c}) => (a[c] = (a[c] ?? 0) + parseFloat(v), a), {});
2. Expanding the consolidated object(s) into an array of objects
Once we have our simplified object (e.g. {a: 66, b: 46, c: 61}) for each array of objects, our next task is to transform it back into the series of objects format we started with, but now consolidated. To do this, we first convert our new object of key-value pairs into an array of nested arrays using the Object.entries() method. This will allow us to re-map the array as an array of objects, during which we'll rewrite our desired key names and convert our numbered values back into strings with a fixed decimal count of 2.
In an earlier step, we destructured an object using its property names. This time, because Object.entries() returns our data as an array, we'll be using array destructuring. This is similar to object destructuring, except that we'll need to use brackets when we restructure our array. Remember to always wrap your destructured parameters in parentheses or you'll get an error:
// obj = {a: 66, b: 46, c: 61};
Object.entries(obj).map([c, v] => ({ value: v.toFixed(2), category: c }))
// !!! Uncaught SyntaxError: Malformed arrow function parameter list
Object.entries(obj).map(([c, v]) => ({ value: v.toFixed(2), category: c }))
/* -> [
{value: "66.00", category: "a"},
{value: "46.00", category: "b"},
{value: "61.00", category: "c"}
]
*/
3. Putting it all together. The final result:
Now all that's left is to put it all together! Here's the final result:
const data = [
[
{value: "10.50", category: "a"},
{value: "55.50", category: "a"},
{value: "10.50", category: "b"},
{value: "35.50", category: "b"},
{value: "15.50", category: "c"},
{value: "45.50", category: "c"}
],
// [ ... ]
];
const consolidate = arr => arr.map(e => Object.entries(e.reduce((a, {value: v, category: c}) => (a[c] = (a[c] ?? 0) + parseFloat(v), a), {})).map(([c, v]) => ({ value: v.toFixed(2), category: c })));
console.log(consolidate(data));