[javascript] Finding the max value of an attribute in an array of objects

I'm looking for a really quick, clean and efficient way to get the max "y" value in the following JSON slice:

[
  {
    "x": "8/11/2009",
    "y": 0.026572007
  },
  {
    "x": "8/12/2009",
    "y": 0.025057454
  },
  {
    "x": "8/13/2009",
    "y": 0.024530916
  },
  {
    "x": "8/14/2009",
    "y": 0.031004457
  }
]

Is a for-loop the only way to go about it? I'm keen on somehow using Math.max.

This question is related to javascript json

The answer is


Here is the shortest solution (One Liner) ES6:

Math.max(...values.map(o => o.y));

Or a simple sort! Keeping it real :)

array.sort((a,b)=>a.y<b.y)[0].y

It's very simple

     const array1 = [
  {id: 1, val: 60},
  {id: 2, val: 2},
  {id: 3, val: 89},
  {id: 4, val: 78}
];
const array2 = [1,6,8,79,45,21,65,85,32,654];
const max = array1.reduce((acc, item) => acc = acc > item.val ? acc : item.val, 0);
const max2 = array2.reduce((acc, item) => acc = acc > item ? acc : item, 0);

console.log(max);
console.log(max2);

I'd like to explain the terse accepted answer step-by-step:

_x000D_
_x000D_
var objects = [{ x: 3 }, { x: 1 }, { x: 2 }];_x000D_
_x000D_
// array.map lets you extract an array of attribute values_x000D_
var xValues = objects.map(function(o) { return o.x; });_x000D_
// es6_x000D_
xValues = Array.from(objects, o => o.x);_x000D_
_x000D_
// function.apply lets you expand an array argument as individual arguments_x000D_
// So the following is equivalent to Math.max(3, 1, 2)_x000D_
// The first argument is "this" but since Math.max doesn't need it, null is fine_x000D_
var xMax = Math.max.apply(null, xValues);_x000D_
// es6_x000D_
xMax = Math.max(...xValues);_x000D_
_x000D_
// Finally, to find the object that has the maximum x value (note that result is array):_x000D_
var maxXObjects = objects.filter(function(o) { return o.x === xMax; });_x000D_
_x000D_
// Altogether_x000D_
xMax = Math.max.apply(null, objects.map(function(o) { return o.x; }));_x000D_
var maxXObject = objects.filter(function(o) { return o.x === xMax; })[0];_x000D_
// es6_x000D_
xMax = Math.max(...Array.from(objects, o => o.x));_x000D_
maxXObject = objects.find(o => o.x === xMax);_x000D_
_x000D_
_x000D_
document.write('<p>objects: ' + JSON.stringify(objects) + '</p>');_x000D_
document.write('<p>xValues: ' + JSON.stringify(xValues) + '</p>');_x000D_
document.write('<p>xMax: ' + JSON.stringify(xMax) + '</p>');_x000D_
document.write('<p>maxXObjects: ' + JSON.stringify(maxXObjects) + '</p>');_x000D_
document.write('<p>maxXObject: ' + JSON.stringify(maxXObject) + '</p>');
_x000D_
_x000D_
_x000D_

Further information:


Each array and get max value with Math.

data.reduce((max, b) => Math.max(max, b.costo), data[0].costo);

ES6 solution

Math.max(...array.map(function(o){return o.y;}))

For more details see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/max


clean and simple ES6 (Babel)

const maxValueOfY = Math.max(...arrayToSearchIn.map(o => o.y), 0);

The second parameter should ensure a default value if arrayToSearchIn is empty.


Find the object whose property "Y" has the greatest value in an array of objects

One way would be to use Array reduce..

const max = data.reduce(function(prev, current) {
    return (prev.y > current.y) ? prev : current
}) //returns object

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce http://caniuse.com/#search=reduce (IE9 and above)

If you don't need to support IE (only Edge), or can use a pre-compiler such as Babel you could use the more terse syntax.

const max = data.reduce((prev, current) => (prev.y > current.y) ? prev : current)

if you (or, someone here) are free to use lodash utility library, it has a maxBy function which would be very handy in your case.

hence you can use as such:

_.maxBy(jsonSlice, 'y');

var max = 0;                
jQuery.map(arr, function (obj) {
  if (obj.attr > max)
    max = obj.attr;
});

// Here is very simple way to go:

// Your DataSet.

let numberArray = [
  {
    "x": "8/11/2009",
    "y": 0.026572007
  },
  {
    "x": "8/12/2009",
    "y": 0.025057454
  },
  {
    "x": "8/13/2009",
    "y": 0.024530916
  },
  {
    "x": "8/14/2009",
    "y": 0.031004457
  }
]

// 1. First create Array, containing all the value of Y
let result = numberArray.map((y) => y)
console.log(result) // >> [0.026572007,0.025057454,0.024530916,0.031004457]

// 2.
let maxValue = Math.max.apply(null, result)
console.log(maxValue) // >> 0.031004457

Well, first you should parse the JSON string, so that you can easily access it's members:

var arr = $.parseJSON(str);

Use the map method to extract the values:

arr = $.map(arr, function(o){ return o.y; });

Then you can use the array in the max method:

var highest = Math.max.apply(this,arr);

Or as a one-liner:

var highest = Math.max.apply(this,$.map($.parseJSON(str), function(o){ return o.y; }));

Comparison of three ONELINERS which handle minus numbers case (input in a array):

var maxA = a.reduce((a,b)=>a.y>b.y?a:b).y; // 30 chars time complexity:  O(n)

var maxB = a.sort((a,b)=>b.y-a.y)[0].y;    // 27 chars time complexity:  O(nlogn)
           
var maxC = Math.max(...a.map(o=>o.y));     // 26 chars time complexity: >O(2n)

editable example here. Ideas from: maxA, maxB and maxC (side effect of maxB is that array a is changed because sort is in-place).

_x000D_
_x000D_
var a = [
  {"x":"8/11/2009","y":0.026572007},{"x":"8/12/2009","y":0.025057454},    
  {"x":"8/14/2009","y":0.031004457},{"x":"8/13/2009","y":0.024530916}
]

var maxA = a.reduce((a,b)=>a.y>b.y?a:b).y;
var maxC = Math.max(...a.map(o=>o.y));
var maxB = a.sort((a,b)=>b.y-a.y)[0].y;

document.body.innerHTML=`<pre>maxA: ${maxA}\nmaxB: ${maxB}\nmaxC: ${maxC}</pre>`;
_x000D_
_x000D_
_x000D_

For bigger arrays the Math.max... will throw exception: Maximum call stack size exceeded (Chrome 76.0.3809, Safari 12.1.2, date 2019-09-13)

_x000D_
_x000D_
let a = Array(400*400).fill({"x": "8/11/2009", "y": 0.026572007 }); 

// Exception: Maximum call stack size exceeded

try {
  let max1= Math.max.apply(Math, a.map(o => o.y));
} catch(e) { console.error('Math.max.apply:', e.message) }

try {
  let max2= Math.max(...a.map(o=>o.y));
} catch(e) { console.error('Math.max-map:', e.message) }
_x000D_
_x000D_
_x000D_

Benchmark for the 4 element array