sinusGob
sinusGob

Reputation: 4303

How to do reduce math.max to an array of objects

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.

Upvotes: 6

Views: 1441

Answers (5)

Mutoo
Mutoo

Reputation: 111

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 comparison.

[
    {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});

Upvotes: 0

Phil
Phil

Reputation: 164731

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 compared numerically) so on the second iteration, you will be trying to compare 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

Upvotes: 4

Felix Kling
Felix Kling

Reputation: 816272

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 completeness, 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.

Upvotes: 2

Feathercrown
Feathercrown

Reputation: 2591

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:""}));

Upvotes: 0

Anurag Awasthi
Anurag Awasthi

Reputation: 6223

Done 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)

Upvotes: 10

Related Questions