# Find max value in a sparse javascript array

Is there a proper way to find the max value of a sparse array with undefined values?

Thanks

var testArr=[undefined,undefined,undefined,3,4,5,6,7]; console.log('max value with undefined is ',(Math.max.apply(null,testArr))); // max value with undefined is NaN console.log('max with arr.max()',testArr.max()); // Error: testArr.max is not a function testArr=[null,null,null,3,4,5,6,7]; console.log('max value with null is ',(Math.max.apply(null,testArr))); // max value with null is 7

I'd prefer not to do forEach if there is a built-in method.

## Answers

testArr.reduce(function(a,b){ if (isNaN(a) || a === null || a === '') a = -Infinity; if (isNaN(b) || b === null || b === '') b = -Infinity; return Math.max(a,b) }, -Infinity);

None of your examples are true sparse arrays (they don't have any 'holes'), but you could use Array.prototype.filter (ECMA5) to test the value isFinite. For better accuracy ECMA6 will offer Number.isFinite. Remember there are also limits to the number of arguments that Function.prototype.apply can handle (often 65536 arguments). Of course, isFinite may not be suitable for your application, if you want Infinity and -Infinity, then you should use a different test. An empty string with negative numbers would be an issue in this current exampe.

var testArr = [undefined, , , 3, 4, 5, 6, 7]; document.body.textContent = Math.max.apply(null, testArr.filter(function (x) { return isFinite(x); }));

I would personally filter it first, and then run it through reduce. Like so:

someArray.filter(function(a){ return isFinite(a) && a !== null && a !== ""; }).reduce(function(a,b){ return a > b ? a : b; });

The reasoning behind this is that *anything* can be inside the Array. isFinite() and the two comparisons would filter out the harmful bits that would make our later comparisons fail. Let's break down the three comparisons:

##### isFinite(a)

The first check is because NaN and friends compare false to everything when using the greater than or less than operator, so:

undefined > 2 == false undefined < 2 == false NaN > 2 == false NaN < 2 == false

##### a !== null

null isn't a problem if you have all positive numbers, but if you have negatives, they are considered greater than them:

null > -1 == true null < -1 == false

##### a !== ""

The same problem we have with null, we have with empty strings:

"" > -1 == true "" < -1 == false

But we don't want to simply eliminate all strings, because some numbers could be inside of them... Like in the case of "-1" and such. This is the reason we don't simply condense the two checks into a typeof compare...

With those out of the way, I would recommend reduce because Function.prototype.apply() can only take a finite number of arguments, so if you have a *giant* array, it won't fail like if you use Math.max.apply().

So, edge cases like this will still yield the correct result:

var junk = ["","-1",-4,null,undefined,NaN,Infinity,,-Infinity]; document.body.textContent = junk.filter(function(a){ return isFinite(a) && a !== null && a !== ""; }).reduce(function(a,b){ return a > b ? a : b; });