Mastering Array Transformations: A Journey Through LeetCode Practice Exercise
Introduction:
Array transformations are fundamental operations in programming, and mastering them is essential for tackling a wide range of algorithmic problems. In this article, we will journey through LeetCode's practice exercises on array transformations. We will explore array transformation with Javascript to deeply dive into Map, Filter, and Reduce Methods. Arrays are versatile data structures that can be transformed in various ways using functional programming techniques. In this article, we will explore three powerful array methods: map
, filter
, and reduce
. We will also delve into how we can achieve array transformations without using these main methods by having a peek at how I solved someLeetCode's problems without the main methods.
The Map Method:
The
map
method iterates over each element of an array and applies a callback function to transform each element. It returns a new array containing the results of applying the callback function to each element. Let's consider an example:const numbers = [1, 2, 3, 4, 5]; const squaredNumbers = numbers.map(num => num * num); console.log(squaredNumbers); // Output: [1, 4, 9, 16, 25]
Here, we use the
map
method to square each number in the array, resulting in a new array of squared numbers. As simple as that. You can imagine everything happening in one line of code.In some technical interviews, you might be given a question that forbids the usage of the main
map
function for the iterations but wants you to return a new array with its elements transformed. Let's consider the LeetCode question:To solve this problem. First, we need to iterate through the input integer array
arr
. We will just use the for loop to traverse each element of the array. We are doing this because we need to reach each element in the array and apply a map function to it.The second thing is now to apply the mapping function
fn
for each elementarr[i]
at the indexi
. The question states thatreturnedArray[i] = fn(arr[i], i)
. So we need to pass both the element and its index as arguments to the mapping function.Here is the code to solve the problem:
/** * @param {number[]} arr * @param {Function} fn * @return {number[]} */ const map = function(arr, fn) { let returnedArray = []; // Create an empty array to store the transformed elements for(let i = 0; i < arr.length; i ++) { returnedArray.push(fn(arr[i], i)); // Apply a mapping function to each element and store it into the returnedArray[] } console.log(returnedArray); // prints the returned Array return returnedArray; //Return the resulting array };
Boom. We are done and all the test cases will pass.
The Filter Method:
The
filter
method creates a new array with all elements that pass a test implemented by the provided callback function. It retains only the elements for which the callback function returns true. Let's see an example:const numbers = [1, 2, 3, 4, 5]; const evenNumbers = numbers.filter(num => num % 2 === 0); console.log(evenNumbers); // Output: [2, 4]
The array returned only contains elements that are even numbers, so they have been filtered from the original array. Let's directly go to the LeetCode's question on the filter method.
Until now we all know that to apply the filter function to each element we need to traverse through each element and pass the element and its index to the filter function
fn
. Also, the question states that our filter functionfn(arr[i], i)
evaluates to a truth value. This hint shows us clearly that we need to check for a truthy condition in our solution. Let's 'Elon' the problem:/** * @param {number[]} arr * @param {Function} fn * @return {number[]} */ var filter = function(arr, fn) { let filteredArray = []; // Create an empty array to store filtered elements // map through the array for(let i = 0; i < arr.length; i ++) { // check if each elements passes the criteria from the callback function if(fn(arr[i], i)) { // if the elements pass the criteria then push the elements inside the filteredArray filteredArray.push(arr[i]); } } return filteredArray; };
That's it for the "Filter Elements of Array" question. We did not use any
Array.filter
method.The Reduce Method.
The
reduce
method applies a function against an accumulator and each element in the array (from left to right) to reduce it to a single value. It is particularly useful for aggregating data or performing calculations on array elements. Here's an example:const numbers = [1, 2, 3, 4, 5]; const sum = numbers.reduce((accumulator, currentValue) => accumulator + currentValue, 0); console.log(sum); // Output: 15
According to the mdn web docs. The first time that the callback is run there is no "return value of the previous calculation". If supplied, an initial value may be used in its place. Otherwise, the array element at index 0 is used as the initial value and iteration starts from the next element (index 1 instead of index 0).
Let's solve a LeetCode question on the same but without using the
Array.map
function:According to the question we need to iterate through the array of numbers
nums
. For each element of the array we need to passinit
and the current element iterated in our case isnums[i]
. After iterating the first element then our next initial value will be the result of the previous functionfn(init, nums[0])
. That's the accumulator. The hint is very straightforward with us, our function will have to look like this:fn(val, nums[i])
pretty easy right? But then the question says that if the length of thenums
array is 0, we should returninit
. Nice let's write some code:/** * @param {number[]} nums * @param {Function} fn * @param {number} init * @return {number} */ var reduce = function(nums, fn, init) { let val= init; if (nums.length < 1) { return init; // Return init if the array is empty } for (let i = 0; i < nums.length; i ++) { val= fn(val, nums[i]); // pass the val and element to the reducer function. } return result; };
That's it. We've done it. Now you know how to work with the
map
,filter
, andreduce
array methods to perform array transformations.
Conclusion:
In this article, we've explored array transformation techniques in JavaScript using the map
, filter
, and reduce
methods. These methods provide powerful tools for manipulating arrays and transforming their elements based on specific criteria. Additionally, we've seen how we can achieve similar transformations using callback functions directly, providing insight into the underlying mechanics of array manipulation in JavaScript. By mastering these techniques, you'll be well-equipped to tackle a wide range of array transformation tasks in your JavaScript projects. Happy coding!