How to find min element in array javascript?

How about augmenting the built-in Array object to use Math.max/Math.min instead:

Array.prototype.max = function[] {
  return Math.max.apply[null, this];
};

Array.prototype.min = function[] {
  return Math.min.apply[null, this];
};

let p = [35,2,65,7,8,9,12,121,33,99];

console.log[`Max value is: ${p.max[]}` +
  `\nMin value is: ${p.min[]}`];

Here is a JSFiddle.

Augmenting the built-ins can cause collisions with other libraries [some see], so you may be more comfortable with just apply'ing Math.xxx[] to your array directly:

var min = Math.min.apply[null, arr],
    max = Math.max.apply[null, arr];

Alternately, assuming your browser supports ECMAScript 6, you can use spread syntax which functions similarly to the apply method:

var min = Math.min[ ...arr ],
    max = Math.max[ ...arr ];

RobG

137k30 gold badges167 silver badges205 bronze badges

answered Nov 3, 2009 at 18:23

Roatin MarthRoatin Marth

22.8k3 gold badges51 silver badges55 bronze badges

14

For big arrays [~10⁷ elements], Math.min and Math.max both produces the following error in Node.js.

RangeError: Maximum call stack size exceeded

A more robust solution is to not add every element to the call stack, but to instead pass an array:

function arrayMin[arr] {
  return arr.reduce[function [p, v] {
    return [ p < v ? p : v ];
  }];
}

function arrayMax[arr] {
  return arr.reduce[function [p, v] {
    return [ p > v ? p : v ];
  }];
}

If you are concerned about speed, the following code is ~3 times faster then Math.max.apply is on my computer. See //jsben.ch/JPOyL.

function arrayMin[arr] {
  var len = arr.length, min = Infinity;
  while [len--] {
    if [arr[len] < min] {
      min = arr[len];
    }
  }
  return min;
};

function arrayMax[arr] {
  var len = arr.length, max = -Infinity;
  while [len--] {
    if [arr[len] > max] {
      max = arr[len];
    }
  }
  return max;
};

If your arrays contains strings instead of numbers, you also need to coerce them into numbers. The below code does that, but it slows the code down ~10 times on my machine. See //jsben.ch/uPipD.

function arrayMin[arr] {
  var len = arr.length, min = Infinity;
  while [len--] {
    if [Number[arr[len]] < min] {
      min = Number[arr[len]];
    }
  }
  return min;
};

function arrayMax[arr] {
  var len = arr.length, max = -Infinity;
  while [len--] {
    if [Number[arr[len]] > max] {
      max = Number[arr[len]];
    }
  }
  return max;
};

answered Nov 18, 2012 at 14:00

Linus UnnebäckLinus Unnebäck

20.9k12 gold badges70 silver badges85 bronze badges

6

Using spread operator [ES6]

Math.max[...array]  // The same with "min" => Math.min[...array]

Gass

4,8172 gold badges17 silver badges29 bronze badges

answered Aug 23, 2016 at 16:37

Abdennour TOUMIAbdennour TOUMI

79.5k36 gold badges233 silver badges239 bronze badges

10

tl;dr

// For regular arrays:
var max = Math.max[...arrayOfNumbers];

// For arrays with tens of thousands of items:
let max = testArray[0];
for [let i = 1; i < testArrayLength; ++i] {
  if [testArray[i] > max] {
    max = testArray[i];
  }
}

MDN solution

The official MDN docs on Math.max[] already covers this issue:

The following function uses Function.prototype.apply[] to find the maximum element in a numeric array. getMaxOfArray[[1, 2, 3]] is equivalent to Math.max[1, 2, 3], but you can use getMaxOfArray[] on programmatically constructed arrays of any size.

function getMaxOfArray[numArray] {
    return Math.max.apply[null, numArray];
}

Or with the new spread operator, getting the maximum of an array becomes a lot easier.

var arr = [1, 2, 3];
var max = Math.max[...arr];

Maximum size of an array

According to MDN the apply and spread solutions had a limitation of 65536 that came from the limit of the maximum number of arguments:

But beware: in using apply this way, you run the risk of exceeding the JavaScript engine's argument length limit. The consequences of applying a function with too many arguments [think more than tens of thousands of arguments] vary across engines [JavaScriptCore has hard-coded argument limit of 65536], because the limit [indeed even the nature of any excessively-large-stack behavior] is unspecified. Some engines will throw an exception. More perniciously, others will arbitrarily limit the number of arguments actually passed to the applied function. To illustrate this latter case: if such an engine had a limit of four arguments [actual limits are of course significantly higher], it would be as if the arguments 5, 6, 2, 3 had been passed to apply in the examples above, rather than the full array.

They even provide a hybrid solution which doesn't really have good performance compared to other solutions. See performance test below for more.

In 2019 the actual limit is the maximum size of the call stack. For modern Chromium based desktop browsers this means that when it comes to finding min/max with apply or spread, practically the maximum size for numbers only arrays is ~120000. Above this, there will be a stack overflow and the following error will be thrown:

RangeError: Maximum call stack size exceeded

With the script below [based on this blog post], by catching that error you can calculate the limit for your specific environment.

Warning! Running this script takes time and depending on the performance of your system it might slow or crash your browser/system!

let testArray = Array.from[{length: 10000}, [] => Math.floor[Math.random[] * 2000000]];
for [i = 10000; i < 1000000; ++i] {
  testArray.push[Math.floor[Math.random[] * 2000000]];
  try {
    Math.max.apply[null, testArray];
  } catch [e] {
    console.log[i];
    break;
  }
}

Performance on large arrays

Based on the test in EscapeNetscape's comment I created some benchmarks that tests 5 different methods on a random number only array with 100000 items.

In 2019, the results show that the standard loop [which BTW doesn't have the size limitation] is the fastest everywhere. apply and spread comes closely after it, then much later MDN's hybrid solution then reduce as the slowest.

Almost all tests gave the same results, except for one where spread somewhy ended up being the slowest.

If you step up your array to have 1 million items, things start to break and you are left with the standard loop as a fast solution and reduce as a slower.

JSPerf benchmark

JSBen benchmark

JSBench.me benchmark

Benchmark source code

answered Jun 14, 2015 at 21:22

totymedlitotymedli

27.2k20 gold badges127 silver badges158 bronze badges

4

If you're paranoid like me about using Math.max.apply [which could cause errors when given large arrays according to MDN], try this:

function arrayMax[array] {
  return array.reduce[function[a, b] {
    return Math.max[a, b];
  }];
}

function arrayMin[array] {
  return array.reduce[function[a, b] {
    return Math.min[a, b];
  }];
}

Or, in ES6:

function arrayMax[array] {
  return array.reduce[[a, b] => Math.max[a, b]];
}

function arrayMin[array] {
  return array.reduce[[a, b] => Math.min[a, b]];
}

The anonymous functions are unfortunately necessary [instead of using Math.max.bind[Math] because reduce doesn't just pass a and b to its function, but also i and a reference to the array itself, so we have to ensure we don't try to call max on those as well.

answered Jul 27, 2015 at 1:00

7

Alternative Methods

The Math.min and Math.max are great methods to get the minimum and maximum item out of a collection of items, however it's important to be aware of some cavities that can comes with it.

Using them with an array that contains large number of items [more than ~10⁷ items, depends on the user's browser] most likely will crash and give the following error message:

const arr = Array.from[Array[1000000].keys[]];
Math.min[arr];
Math.max[arr];

Uncaught RangeError: Maximum call stack size exceeded

UPDATE
Latest browsers might return NaN instead. That might be a better way to handle errors, however it doesn't solve the problem just yet.

Instead, consider using something like so:

function maxValue[arr] {
  return arr.reduce[[max, val] => max > val ? max : val]
}

Or with better run-time:

function maxValue[arr] {
  let max = arr[0];

  for [let val of arr] {
    if [val > max] {
      max = val;
    }
  }
  return max;
}

Or to get both Min and Max:

function getMinMax[arr] {
  return arr.reduce[[{min, max}, v] => [{
    min: min < v ? min : v,
    max: max > v ? max : v,
  }], { min: arr[0], max: arr[0] }];
}

Or with even better run-time*:

function getMinMax[arr] {
  let min = arr[0];
  let max = arr[0];
  let i = arr.length;
    
  while [i--] {
    min = arr[i] < min ? arr[i] : min;
    max = arr[i] > max ? arr[i] : max;
  }
  return { min, max };
}

* Tested with 1,000,000 items:
Just for a reference, the 1st function run-time [on my machine] was 15.84ms vs 2nd function with only 4.32ms.

answered Oct 2, 2018 at 17:34

Lior ElromLior Elrom

18.3k16 gold badges76 silver badges90 bronze badges

3

Two ways are shorter and easy:

let arr = [2, 6, 1, 0]

Way 1:

let max = Math.max.apply[null, arr]

Way 2:

let max = arr.reduce[function[a, b] {
    return Math.max[a, b];
}];

answered May 18, 2018 at 1:37

3

.apply is often used when the intention is to invoke a variadic function with a list of argument values, e.g.

The Math.max[[value1[,value2, ...]]] function returns the largest of zero or more numbers.

Math.max[10, 20]; // 20
Math.max[-10, -20]; // -10
Math.max[-10, 20]; // 20

The Math.max[] method doesn't allow you to pass in an array. If you have a list of values of which you need to get the largest, you would normally call this function using Function.prototype.apply[], e.g.

Math.max.apply[null, [10, 20]]; // 20
Math.max.apply[null, [-10, -20]]; // -10
Math.max.apply[null, [-10, 20]]; // 20

However, as of the ECMAScript 6 you can use the spread operator:

The spread operator allows an expression to be expanded in places where multiple arguments [for function calls] or multiple elements [for array literals] are expected.

Using the spread operator, the above can be rewritten as such:

Math.max[...[10, 20]]; // 20
Math.max[...[-10, -20]]; // -10
Math.max[...[-10, 20]]; // 20

When calling a function using the variadic operator, you can even add additional values, e.g.

Math.max[...[10, 20], 50]; // 50
Math.max[...[-10, -20], 50]; // 50

Bonus:

Spread operator enables you to use the array literal syntax to create new arrays in situations where in ES5 you would need to fall back to imperative code, using a combination of push, splice, etc.

let foo = ['b', 'c'];
let bar = ['a', ...foo, 'd', 'e']; // ['a', 'b', 'c', 'd', 'e']

answered Dec 18, 2014 at 1:38

GajusGajus

64.5k68 gold badges262 silver badges417 bronze badges

1

You do it by extending the Array type:

Array.max = function[ array ]{
    return Math.max.apply[ Math, array ];
};
Array.min = function[ array ]{
    return Math.min.apply[ Math, array ];
}; 

Boosted from here [by John Resig]

answered Nov 3, 2009 at 18:35

brettkellybrettkelly

27k8 gold badges53 silver badges70 bronze badges

A simple solution to find the minimum value over an Array of elements is to use the Array prototype function reduce:

A = [4,3,-9,-2,2,1];
A.reduce[[min, val] => val < min ? val : min, A[0]]; // returns -9

or using JavaScript's built-in Math.Min[] function [thanks @Tenflex]:

A.reduce[[min,val] => Math.min[min,val], A[0]];

This sets min to A[0], and then checks for A[1]...A[n] whether it is strictly less than the current min. If A[i] < min then min is updated to A[i]. When all array elements has been processed, min is returned as the result.

EDIT: Include position of minimum value:

A = [4,3,-9,-2,2,1];
A.reduce[[min, val] => val < min._min ? {_min: val, _idx: min._curr, _curr: min._curr + 1} : {_min: min._min, _idx: min._idx, _curr: min._curr + 1}, {_min: A[0], _idx: 0, _curr: 0}]; // returns { _min: -9, _idx: 2, _curr: 6 }

answered Oct 29, 2017 at 11:26

2

For a concise, modern solution, one can perform a reduce operation over the array, keeping track of the current minimum and maximum values, so the array is only iterated over once [which is optimal]. Destructuring assignment is used here for succinctness.

let array = [100, 0, 50];
let [min, max] = array.reduce[[[prevMin,prevMax], curr]=>
   [Math.min[prevMin, curr], Math.max[prevMax, curr]], [Infinity, -Infinity]];
console.log["Min:", min];
console.log["Max:", max];

To only find either the minimum or maximum, we can use perform a reduce operation in much the same way, but we only need to keep track of the previous optimal value. This method is better than using apply as it will not cause errors when the array is too large for the stack.

const arr = [-1, 9, 3, -6, 35];

//Only find minimum
const min = arr.reduce[[a,b]=>Math.min[a,b], Infinity];
console.log["Min:", min];//-6

//Only find maximum
const max = arr.reduce[[a,b]=>Math.max[a,b], -Infinity];
console.log["Max:", max];//35

answered Aug 20, 2020 at 22:47

UnmitigatedUnmitigated

48.7k7 gold badges49 silver badges64 bronze badges

Others have already given some solutions in which they augment Array.prototype. All I want in this answer is to clarify whether it should be Math.min.apply[ Math, array ] or Math.min.apply[ null, array ]. So what context should be used, Math or null?

When passing null as a context to apply, then the context will default to the global object [the window object in the case of browsers]. Passing the Math object as the context would be the correct solution, but it won't hurt passing null either. Here's an example when null might cause trouble, when decorating the Math.max function:

// decorate Math.max
[function [oldMax] {
    Math.max = function [] {
        this.foo[]; // call Math.foo, or at least that's what we want

        return oldMax.apply[this, arguments];
    };
}][Math.max];

Math.foo = function [] {
    print["foo"];
};

Array.prototype.max = function[] {
  return Math.max.apply[null, this]; //  current ? previous:current
                   }];

b => 11
arr => [1, 10, 5, 11, 2]

2

This may suit your purposes.

Array.prototype.min = function[comparer] {

    if [this.length === 0] return null;
    if [this.length === 1] return this[0];

    comparer = [comparer || Math.min];

    var v = this[0];
    for [var i = 1; i < this.length; i++] {
        v = comparer[this[i], v];    
    }

    return v;
}

Array.prototype.max = function[comparer] {

    if [this.length === 0] return null;
    if [this.length === 1] return this[0];

    comparer = [comparer || Math.max];

    var v = this[0];
    for [var i = 1; i < this.length; i++] {
        v = comparer[this[i], v];    
    }

    return v;
}

answered Nov 3, 2009 at 18:21

ChaosPandionChaosPandion

76.1k17 gold badges117 silver badges154 bronze badges

5

let array = [267, 306, 108] let longest = Math.max[...array];

answered Oct 3, 2020 at 15:10

Trilok SinghTrilok Singh

1,05911 silver badges8 bronze badges

1

I thought I'd share my simple and easy to understand solution.

For the min:

var arr = [3, 4, 12, 1, 0, 5];
var min = arr[0];
for [var k = 1; k < arr.length; k++] {
  if [arr[k] < min] {
    min = arr[k];
  }
}
console.log["Min is: " + min];

And for the max:

var arr = [3, 4, 12, 1, 0, 5];
var max = arr[0];
for [var k = 1; k < arr.length; k++] {
  if [arr[k] > max] {
    max = arr[k];
  }
}
console.log["Max is: " + max];

answered Oct 13, 2016 at 16:37

IonutIonut

10.7k4 gold badges43 silver badges69 bronze badges

9

For big arrays [~10⁷ elements], Math.min and Math.max procuces a RangeError [Maximum call stack size exceeded] in node.js.

For big arrays, a quick & dirty solution is:

Array.prototype.min = function[] {
    var r = this[0];
    this.forEach[function[v,i,a]{if [v 
x -  y]
let min_val = nums[0]
let max_val = nums[nums.length -1]

answered Feb 14, 2020 at 15:29

Chukwu3mekaChukwu3meka

4,2954 gold badges28 silver badges52 bronze badges

1

I had the same problem, I needed to obtain the minimum and maximum values of an array and, to my surprise, there were no built-in functions for arrays. After reading a lot, I decided to test the "top 3" solutions myself:

  1. discrete solution: a FOR loop to check every element of the array against the current max and/or min value;
  2. APPLY solution: sending the array to the Math.max and/or Math.min internal functions using apply[null,array];
  3. REDUCE solution: recursing a check against every element of the array using reduce[function].

The test code was this:

function GetMaxDISCRETE[A]
{   var MaxX=A[0];

    for [var X=0;X

Chủ Đề