Working with minimum and maximum values
Finding the greater of two numbers
JavaScript’s Math
object provides some good methods for simple calculations and comparisons.
For example, finding the greater of two numbers is easy:
console.log(Math.max(23, 19)); // 23
We can use the max
method available on the Math
object. It accepts numbers as arguments and returns the highest of these numbers.
If a value cannot be converted to a number, it returns NaN
, which is a falsy value:
console.log(Math.max(41, 'dog')); // NaN
What if we have an array of numbers and need to find the greatest of these numbers? We don’t necessarily know how many elements the array has!
Getting the greatest value in an array
Arrays cannot be passed as an argument to Math.max
, hence we need to apply a trick here.
Before ES6, we could use apply
to call Math.max
with a list of arguments:
const numbers = [5, 23, -2, -19, 11];
console.log(Math.max.apply(null, numbers)); // 23
apply
calls the function (in our case Math.max
) with a pre-defined this
value (in our case null
because we don’t need any special context other than global) as the first argument and an array (second argument, numbers
in our case).
Although apply
is great and can be used in many situations, ES6 provides a nice and easy solution with the spread operator, which makes individual arguments for the Math.max
method from the elements of the array:
console.log(Math.max(...numbers)); // 23
I personally think that the ES6 way is easier and more elegant than apply
, so I give it the thumbs up.
In case of large number (like tens of thousands) of elements in the array these solutions might not work properly as the number of arguments applied to a function can be limited by some engines.
We can solve this problem with sorting the numbers first in descending order and then accessing the first element:
const returnMax = (arr) => {
return arr.sort((a, b) => a < b)[0];
};
console.log(returnMax(numbers)); // 23
Or, an even simpler solution is to use reduce
:
const returnMax2 = (arr) => {
return arr.reduce((a, b) => Math.max(a, b));
};
console.log(returnMax2(numbers)); // 23
The methods work similarly for Math.min
as well.
Minimum absolute difference
An interesting problem is to find the minimum absolute difference of any two numbers in the numbers
array.
We can solve this problem with the brute force approach using two for
loops, for example, but it’s so cumbersome that I don’t even show it.
Instead of comparing each element to all other elements, calculating the difference of each pair and returning the smallest of all differences, let’s have a look at another, more efficient solution.
Sort the numbers first
What if we sorted the numbers from smallest to greatest first? We could then iterate over them and compare each number with the one on its right. This way we can get away with just one iteration instead of two and still receive the same result.
Get the result with one iteration
Here’s how:
function minimumAbsoluteDifference(arr) {
const sorted = arr.sort((a, b) => a - b);
let min = Number.MAX_VALUE;
for (let i = 0; i < arr.length - 1; i++) {
const diff = sorted[i + 1] - sorted[i];
if (diff < min) min = diff;
}
return min;
}
This is what we get after sorting the elements of numbers
:
console.log(sorted); // [-19, -2, 5, 11, 23]
After getting the numbers in ascending order, we define an initial value for min
(refers to the minimum difference) as being the highest number available in JavaScript. We can also assign the difference between the last and the first elements (the highest and the lowest values) of numbers
to min
, which is also a good initial value.
There’s not much magic inside the for
statement. We define the difference (diff
) on each iteration by subtracting the value with the smaller index (sorted[i]
) from the one with the greater index (sorted[i + 1]
).
Because sorted
has the numbers in ascending order, it’s guaranteed that numbers coming later in the array won’t be smaller than the previous ones, so diff
will always be non-negative, which is a requirement for a difference (difference is defined as an absolute value and it can’t be negative).
If diff
, which is redefined on each iteration is smaller than the current value of min
, we simply store the new minimum in min
.
Once the loop has finished, we return min
.
Let’s call the function:
console.log(minimumAbsoluteDifference(numbers)); // 6
We got 6
, which is the difference between 5 and 11. As it can be seen this is the smallest difference of any two numbers in numbers
.
Conclusion
That’s it for today. Again, often times we can find a nice, short and elegant solution instead of the brute force approach.
See you next time.