6

I need to calculate min/max of large array. I know about Math.max.apply(), but on large arrays it fails with Stack overflow exception. Any simple solutions?

karthikr
  • 97,368
  • 26
  • 197
  • 188

7 Answers7

6
  1. Sort the array by using sort() method it sorts array by using quicksort algorithm

  2. Since array is sorted in ascending order then the last element is the max

    var arr = [1,4,6,4, ...];
    arr.sort((a, b) => a - b);
    var max = arr[arr.length - 1];
    
Zarel
  • 2,201
  • 1
  • 15
  • 20
Nick
  • 4,192
  • 1
  • 19
  • 30
  • 2
    You answer made me feel really stupid :(. In fact I already have sorted array. That's why you want code reviews... – Alexey Timanovsky Jun 05 '13 at 19:12
  • Just keep it DRY = Don't Repeat Yourself :) – Nick Jun 05 '13 at 19:23
  • 5
    It's only worth sorting the array if you're going to be doing some binary searches [O(log n)] on the array anyways. If you want to get the max and min you might as well loop through every element since O(n) is faster than O(n log n). For lots of large arrays this might matter... – David Sherret Jun 05 '13 at 19:23
  • 1
    Sure. I have sorted array in order to calculate percentiles. Having min/max is a nice side effect :) – Alexey Timanovsky Jun 05 '13 at 19:35
  • You can slightly simplify this by sorting in descending order, which allows just getting the first element. I.e. `arr.sort((a, b) => b - a)[0]` – micahbf May 12 '23 at 15:35
3
Array.prototype.min = function() {
    var r = this[0];
    this.forEach(function(v,i,a){if (v<r) r=v;});
    return r;
};

From JavaScript: min & max Array values? where other solutions from this problem are discussed

FYI: I just googled "max min large array" and found this as the first result...

Community
  • 1
  • 1
Antoine
  • 2,785
  • 1
  • 16
  • 23
2

Why not just loop through the entire array?

var max = Number.MIN_VALUE, min = Number.MAX_VALUE;
for (var i = 0, len=list.length; i < len; i++) {
   if (list[i] > max) max = list[i];
   if (list[i] < min) min = list[i];
}

Edit:

For max:

if (typeof Array.prototype.GetMax === "undefined") {
    Array.prototype.GetMax = function() {
        var max = Number.MAX_VALUE;
        for (var i = 0, len=this.length; i < len; i++) {
           if (this[i] > max) max = this[i];
        }
        return max;
    }
}

For min:

if (typeof Array.prototype.GetMin === "undefined") {
    Array.prototype.GetMin = function() {
        var min = Number.MIN_VALUE;
        for (var i = 0, len=this.length; i < len; i++) {
           if (this[i] < min) min = this[i];
        }
        return min;
    }
}

For both:

if (typeof Array.prototype.GetMaxMin === "undefined") {
    Array.prototype.GetMaxMin = function() {
        var max = Number.MIN_VALUE, min = Number.MAX_VALUE;
        for (var i = 0, len=this.length; i < len; i++) {
            if (this[i] > max) max = this[i];
            if (this[i] < min) min = this[i];
        }
        return { Max: max, Min: min};
    }
}
David Sherret
  • 101,669
  • 28
  • 188
  • 178
0

Should I assume you have thought of this:

var maxSoFar = -9999999;
for (var i = 0; i < array.length ; ++i) {
    if (array[i] > maxSoFar) {
        maxSoFar = array[i];
    }
    ... similar for minSoFar ...
}
Lee Meador
  • 12,829
  • 2
  • 36
  • 42
0

try this

var arr = [];
for(var i=1000000;i>0;i--)
{
    arr.push(i);
}
//we create a copy of the original array through arr.concat() since we do not want to change the original sorting order of the array
//we pass a function in the sort method as by default it sorts alphabetically instead of numerically. So 99 will be smaller than 100.
var arrMaxMin = arr.concat().sort(function(a,b){return a-b});

arrMaxMin[0]; //min
arrMaxMin[arrMaxMin.length - 1]; //max
Parthik Gosar
  • 10,998
  • 3
  • 24
  • 16
0

Hey why dont you slice your array into smaller arrays then on that arrays you can easily use Math.max.apply(Math,individual arrays).But remember to reinitialize all subarrays back to null so as to get the memory back once desired max value is obtained

chetan mehta
  • 369
  • 1
  • 3
  • 13
0

This is exactly what reduce is for:

function max(arr) {
  if (arr.length === 0) {
    return NaN // or whatever answer you want for an empty array, or throw an error.
  }
  return arr.reduce((a, b) => Math.max(a, b), -Infinity)
}
console.log(max([...new Array(100000).keys()]))

(note that [...new Array(100000).keys()] is just a fancy way in a modern browsers to make a huge array of the numbers 0 to 999999. The max function itself will run in anything made in the last 20 years.)

You can also reduce it to this one-liner:

arr.reduce((cur, val, i) => i === 0 ? val : Math.max(cur, val), NaN)

here NaN is the value you get back if the array is empty

Or even

arr.reduce((a, b) => Math.max(a, b), -Infinity)

although this will return -Infinity for an empty array.

Finally, it may be tempting to just do:

arr.reduce(Math.max, -Infinity)  //don't do this!!

but this won't work. This is because reduce calls it's function (Math.max) with 4 parameters, one of which is the original array, so a Math.max on those will always result in a NaN.

Claude
  • 8,806
  • 4
  • 41
  • 56