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

Need Your Help

sqlserver 2000: how to make aynchoronous call to procedures in database?

java sql-server stored-procedures asynchronous

back end java 1.4 with EJB 3.2 data base sql server 2000 How to make asynchoronous call to a procedure from java code using jdbc?

Using MSXML2.XMLHTTP in Excel VBA to extract large amounts of text data from website

excel vba msxml html-content-extraction

This is my first post here so kindly ignore any mistakes in convention. I have searched long and hard for a solution to this problem on StackOverflow and Google but to no avail.

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.