Optimizing JavaScript
roadpilot
Posted on August 29, 2021
One of my daily code challenges this week was to return the number of occurrences of the max value of an array. At first I just tried the "brute force" iteration approach with a dictionary to keep track of the count:
const ar = [3,2,1,3] // there are 2 3's so 2 should be my result
const dict = {}
for (let i=0; i<ar.length; i++){
if (dict[ar[i]]){
dict[ar[i]]++
} else {
dict[ar[i]]=1
}
}
// console.log(Object.keys(dict).length)
return (Object.values(dict).sort()[Object.keys(dict).length-1])
... which did work but I always like to shoot for a "one-line" solution.
So, I took my iteration and started thinking through the built in prototype.Array functions in JavaScript. I decided to use "filter()" because it will return a sub-set of the original array. Then I can use "length" to get the count of the elements that match the filter. Seems easy enough:
ar.filter(el => el == 3).length // returns 2
My "3" comparison value is just psuedocode for now, only because I already know the max value. Now I have to find the max value so I can make this a dynamic function. I can use "Math.max()" to determine the max value of the array:
Math.max(...ar) // returns 3
// using the spread operator "..." is shorthand for using "apply". The "apply" method could also be used:
Math.max.apply(null, ar)
So now I can just replace my psuedocode value with the function to find the max of the array:
ar.filter(el => el == Math.max(...ar)).length // returns 2
...which does work but since this is a code challenge, the solution times out and fails the test cases (if you do code challenges, you know what this means).
I examined what was happening and noticed that even if a function is nested within another function - on one line or otherwise - it still is a nested function. For every element of the ar filter step, it was checking to find the max value of the array. I'm pretty sure this would be O(n^2). But if I create a variable (maxVal) and assign the max value (Math.max(...ar)) OUTSIDE of the filter function, then the timeout errors go away and all test cases pass:
const maxVal = Math.max(...ar)
return (ar.filter(el => el == maxVal).length)
So, not exactly a one line solution but much leaner and cleaner than the "brute force" method where I started. And a valuable lesson, for sure!
Posted on August 29, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.