Need to reduce an array of Objects to return the highest value of the same name.
Need the following,
[
{
name: 'a',
value: 20,
...(other object values)
},
{
name: 'a',
value: 80
...(other object values)
},
{
name: 'b',
value: 90,
...(other object values)
},
{
name: 'b',
value: 50,
...(other object values)
}
]
To return
[
{
name: 'a',
value: 80
...(other object values)
},
{
name: 'b',
value: 90,
...(other object values)
}
]
I have a solution, but it seems a little to much, wondering if there is a more straightforward way to achieve it?
Below is the solution I could think of:
var toReduce = [
{
'name': 'a',
'value': 20,
'other': 'any',
},
{
'name': 'a',
'value': 80,
'other': 'value',
},
{
'name': 'b',
'value': 90,
'other': 'extra',
},
{
'name': 'b',
'value': 50,
'other': 'super',
}
];
function arrayReducer(arrayToReduce) {
// Created an object separating by name
let reduced = arrayToReduce.reduce((accumulator, currentValue) => {
(accumulator[currentValue.name] =
accumulator[currentValue.name] || []).push(currentValue);
return accumulator;
}, {});
// Reduce object to the highest value
for (let quotes of Object.keys(reduced)) {
reduced[quotes] = reduced[quotes].reduce(
(accumulator, currentValue) => {
return accumulator && accumulator.value > currentValue.value
? accumulator
: currentValue;
}
);
}
// return only object values
return Object.values(reduced);
}
console.log(arrayReducer(toReduce));
The easiest here is probably a simple loop:
const result = {};
for (const item of input) {
if (item.value > (result[item.name]?.value ?? 0)) {
result[item.name] = item;
}
}
// To turn it back into the original array format:
const output = Object.values(result)
Of course you can turn this into a single statement with reduce()
and so on, but legibility will suffer as you can see from all the other answers.
But here's the .reduce()
version using the same approach:
const output = Object.values(
input.reduce( (acc, cur) => {
if (cur.value > (acc[cur.name]?.value ?? 0)) {
acc[cur.name] = cur;
}
return acc;
}, {})
)