DEV Community

Cover image for 🔥 Getting the largest number from an array

🔥 Getting the largest number from an array

Dom Habersack on January 05, 2021

Math.max() returns the largest of zero or more numbers passed to it. We can use the spread operator when passing an array to get the largest number...
Collapse
 
darkwiiplayer profile image
𒎏Wii 🏳️‍⚧️ • Edited
[1, 2, 3, 4, 5, 6].reduce((a,b) => Math.max(a, b)) // EDIT: you can leave the extra argument out ;P
Enter fullscreen mode Exit fullscreen mode

In any sane programming language, you'd just do

[1, 2, 3, 4, 5, 6].fold(math.max)
Enter fullscreen mode Exit fullscreen mode

but alas, JS masterfully breaks every existing pattern except those coming from C.

Collapse
 
oliverradini profile image
OliverRadini

I think you're picking a hole in JS where there isn't one, except, perhaps, in the Math.max function. You could easily create a function which will work very happily with reduce:

const maxOfTwo = (a: number, b: number) => a > b ? a : b;

[1, 2, 3, 4, 5, 6].reduce(maxOfTwo);
Enter fullscreen mode Exit fullscreen mode
Collapse
 
domhabersack profile image
Dom Habersack

Nice alternative! That is the way I used to do this before the spread operator. Works just as well.

You might want to safeguard this with Number.NEGATIVE_INFINITY as the initial value in reduce in case of an empty array. Math.max() also returns -Infinity when called without any parameters.

Thread Thread
 
oliverradini profile image
OliverRadini

That'd surely be worth doing, I really only added that code to give an example close to the code that was quoted.

Thread Thread
 
domhabersack profile image
Dom Habersack

Fair enough. 👍

Collapse
 
darkwiiplayer profile image
𒎏Wii 🏳️‍⚧️

I think you're picking a hole in JS where there isn't one

There definitely is. The problem here is a clash between two good intentions:

  1. Allowing more than two arguments in the max function
  2. Passing extra information to the combining function

The first one is unnecessary. It's only a bit more convenient to write max(a, b, c) than [a, b, c].fold(max), but it's still something that makes sense.

The second one, on the other hand, is a giant footgun. It only makes sense in the context of optimization, as using map first would result in one temporary array being created, but that should be optimized by the language runtime via stream fusion, not by the specification of the function. Ultimately it will just lead to more confusing code full of functions that do too many things at once, giving it a very procedural feel.

As for your solution, that's basically what I did, except that I wrote the function inline. Another solution would be:

const fold (arr, f) => arr.reduce((a, b) => f(a,b))

fold([1, 2, 3, 4, 5, 6], Math.max)
Enter fullscreen mode Exit fullscreen mode

Which, to prevent monkey-patching, sadly loses the method-syntax which makes chaining easier to read.

Collapse
 
dtinth profile image
Thai Pangsakulyanont • Edited

If you don't have to deal with large arrays (more than 100000 elements), then this approach works fine.

However if the array is large, please bear in mind that JavaScript runtimes have a limitation on the number of arguments that you can pass to a function. Yes, this include spread parameters.

If you pass more arguments than the limit, “Maximum call stack size exceeded” errors happen.

I have to find the maximum and minimum value of very huge arrays. For this I'm using

Math.max.apply(Math, my_array);
Math.min.apply(Math, my_array);

It works good on Firefox and IE, but on Chrome I always get Maximum call stack size exceeded errors... my current array has 221954 elements, and that's not my…

Collapse
 
vonheikemen profile image
Heiker

It looks like this works, too.

Math.max.apply(null, [69, 420, 108, 47]);
// => 420
Enter fullscreen mode Exit fullscreen mode