14

I want to select the biggest number in an array of objects, so for example, I want to get the x property that holds the largest number (in this example, maximum should be 200):

var myArr = [{x:100,y:200},{x:200,y:500}];

//does not work:
var maximum = Math.max.apply(Math,myArr.x);
Jon Crowell
  • 21,695
  • 14
  • 89
  • 110
doubleOrt
  • 2,407
  • 1
  • 14
  • 34

7 Answers7

30

You'll have to extract the properties from the objects yourself:

var maximum = Math.max.apply(Math, myArr.map(function(o) { return o.x; }));

That uses .map() to iterate through the elements of the array and return the value of the "x" property. That result array is then passed as the arguments to Math.max().

Now that => functions are widely available it'd be a little shorter as so:

var maximum = Math.max.apply(Math, myArr.map(o => o.x));

Still doing pretty much the exact same thing of course.

Pointy
  • 405,095
  • 59
  • 585
  • 614
  • It's been a long time since and obviously, back then I accepted the answer which I understood easier (the one accepted right now), but it appears from the number of upvotes that your solution is preferred. Could you explain why ? – doubleOrt Oct 31 '17 at 18:29
  • @Taurus well I would suppose it's because it's a lot more succinct. It's not doing anything fundamentally different however. – Pointy Oct 31 '17 at 18:35
7

One more way, I think it is more beautiful. By using spread:

Math.max(...array.map((i) => i.x));
1

You need to map the object array to an array of numbers:

Math.max.apply(Math,myArr.map(function(o){return o.x;}))
Steve Ruble
  • 3,875
  • 21
  • 27
Ameer Hamza
  • 586
  • 3
  • 16
1
var myArr = [{x:100,y:200},{x:200,y:500}];

function sortByKeyDesc(array, key) {
    return array.sort(function(a, b) {
        var x = a[key]; var y = b[key];
        return ((x < y) ? 1 : ((x > y) ? -1 : 0));
    });
}
console.log(sortByKeyDesc(myArr, "x")[0].x);

first sort by key value in descending order and then get the first object's x property

Community
  • 1
  • 1
gurvinder372
  • 66,980
  • 10
  • 72
  • 94
1

If you want to do it the old fashioned way:

function arrayMax(arr, key){
    var m = -Infinity,
        cur,
        i;
    for(i=0; i<arr.length; i++){
        cur = arr[i][key]
        if(cur > m){
            m = cur;
        }
    }
    return m;
}

This function takes an array of objects as the first argument and a key as the second. It iterates over the array and returns the largest value found for the given key.

In your case, you would call it like this:

var maximum = arrayMax(myArr, "x");

Notice that, unlike Math.max, this is resilient to the case where one (or more) of the objects does not have that key defined, so that:

arrayMax([{y:200}, {x:100, y:100}, {x:300, y:400}], "x");

Will return 300, whereas Math.max returns NaN (on Google chrome, at least). Worst case scenario (none of the objects has the key defined), the arrayMax function returns -Infintity.

If you want to return the object that has the largest value instead of simply returning the value, you can easily modify the function to do so:

function arrayMax(arr, key){
    var m = -Infinity,
        o = null,
        cur,
        curv,
        i;
    for(i=0; i<arr.length; i++){
        cur = arr[i]
        curv = cur[key]
        if(curv > m){
            m = curv;
            o = cur;
        }
    }
    return o;
}
0

You may be better off not using Math.max at all.

MDN warns that if you have too many elements in your array, .apply may not work. I'm not sure what "too many" means.

If you want to be safe, use something like this:

const maxReduced = myArr
  .map(obj => {
    return obj.x;
  })
  .reduce((a, b) => (a.x > b.x ? a : b));

MDN Warning

However, both spread (...) and apply will either fail or return the wrong result if the array has too many elements, because they try to pass the array elements as function parameters. See Using apply and built-in functions for more details. The reduce solution does not have this problem.

Jon Crowell
  • 21,695
  • 14
  • 89
  • 110
0
const maximum = myArr.reduce((s, obj)=>{
  return Math.max(s, obj.x)
}, 0)

REASON -

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/max As, both spread (...) and apply will either fail or return the wrong result if the array has too many elements, because they try to pass the array elements as function parameters. See Using apply and built-in functions for more details. The reduce solution does not have this problem.

Abhay
  • 6,410
  • 4
  • 26
  • 34