I have an array of objects. I want to get the max out of the number attribute from the array:
[
{number: 1000, name: "Josh"},
{number: 2000, name: "Joker"},
{number: 3000, name: "Batman"}
]
I'm using this solution but I keep getting NAN
:
const max = arr.reduce((a, b) => Math.max(a.number, b.number));
My goal is to get the max and then store it in a variable
const x = { number: 3000, name: "Batman"}
How would I achieve it with reduce? It seems like it is only working with array of numbers.
I have an array of objects. I want to get the max out of the number attribute from the array:
[
{number: 1000, name: "Josh"},
{number: 2000, name: "Joker"},
{number: 3000, name: "Batman"}
]
I'm using this solution but I keep getting NAN
:
const max = arr.reduce((a, b) => Math.max(a.number, b.number));
My goal is to get the max and then store it in a variable
const x = { number: 3000, name: "Batman"}
How would I achieve it with reduce? It seems like it is only working with array of numbers.
Share Improve this question edited Dec 20, 2018 at 10:29 Patrick Hund 20.2k12 gold badges70 silver badges95 bronze badges asked Dec 20, 2018 at 4:30 sinusGobsinusGob 4,31314 gold badges50 silver badges86 bronze badges 2-
1
Math.max
returns a number. After the first iteration,a
is a number, not an object. – Felix Kling Commented Dec 20, 2018 at 4:37 -
What result are you after? Just the maximum
number
or the object with the highestnumber
? Also, are the any extra conditions to apply if thenumber
is the same? – Phil Commented Dec 20, 2018 at 4:44
5 Answers
Reset to default 11Done by simple reduce,
var arr=[{"number":1000,"name":"Josh"},{"number":2000,"name":"Joker"},{"number":3000,"name":"Batman"}]
var x = arr.reduce((acc, i)=>(i.number > acc.number ? i : acc))
console.log(x)
With Array.prototype.reduce
, you have to remember that the first argument passed to the callback is the accumulator. That is, the return value from the previous iteration.
Math.max
returns a Number
(or NaN
if the operands cannot be pared numerically) so on the second iteration, you will be trying to pare the number
property of a Number
which won't work.
As an alternative to reduce
, you might want to consider sorting the array. This could be beneficial if you want other properties like the smallest value.
// smallest to largest, use "b.number - a.number" to reverse
arr.sort((a, b) => a.number - b.number)
arr[0] // smallest
arr[arr.length - 1] // largest
Math.max
returns a number. After the first iteration, a
is a number, not an object, so a.number
returns undefined
.
When you pass a second argument to .reduce
, you can ensure that the accumulator is always a number. If you only want to get the max number, for pleteness, here is another way to do that:
const max = arr.reduce((a, b) => Math.max(a, b.number), -Infinity);
I'd still rather go with @ntgwsth solution for more flexibility.
You had the right idea. Here's a solution that uses reduce
and keeps tabs on the highest-ranking object in the array:
var nameNum = [
{number: 1000, name: "Josh"},
{number: 2000, name: "Joker"},
{number: 3000, name: "Batman"}
];
console.log(nameNum.reduce(function(max,current){return current.number>max.number?current:max;},{number:-Infinity, name:""}));
In case you really want to use Math.max()
as a part of the reduce callback, here is a sample:
You can create a mock hash map for your options, and use Math.max() to select the right one.
Also, Remember put an initial -Inf object for the very first parison.
[
{number: 1000, name: 'Josh'},
{number: 2000, name: 'Joker'},
{number: 3000, name: 'Batman'},
].reduce((max, current) => {
return {
[max.number]: max,
[current.number]: current,
}[Math.max(max.number, current.number)];
}, {number: -Infinity});