Implement a deepFilterArray function
Deep Filtering is not a standard term defined in JavaScript, but it is commonly well understood as the process of perform filtering operation on each depth of a nested multi-dimensional array.
1. Basic implementation
We have to implement a deepFilterArray()
utility function which takes a nested multi-dimensional array and a filter callback and returns a new array with element filtered. The depth of elements on array must be maintained.
function deepFilterArray(arr, filterFn) { const result = [];
if (!arr.length) { return result; }
arr.forEach((item) => { if (Array.isArray(item)) { // recursively call the filter method when it's a nested array result.push(deepFilterArray(item, filterFn)); } else { const isTruthy = filterFn(item); if (isTruthy) { result.push(item); } } });
return result;}
// Usageconst input = [1, [2, [3, [[4], { a: 1, b: 4 }], 4, 'hi'], ['hello', [['welcome', 10]], 11]]];
const output = deepFilterArray(input, function (e) { return typeof e === 'number' && e > 2;});
/** * Yields: [[[3,[[4]],4],[[[10]],11]]] */console.log(JSON.stringify(output));
2. Custom this binding implementation
In the above implementation, we simply invoked the filter callback, without binding the this
keyword to any value. For this implementation, we need to bind the this
value to the original input array.
Most of the implementation will remain the same, so I am highlighting only the new changes made to support the same.
function deepFilterArray(arr, filterFn, ogArg = arr) { const result = [];
if (!arr.length) { return result; }
arr.forEach((item) => { if (Array.isArray(item)) { result.push(deepFilterArray(item, filterFn, ogArg)); } else { const isTruthy = filterFn.call(ogArg, item); if (isTruthy) { result.push(item); } } });
return result;}
// Usageconst input = [1, [2, [3, [[4], { a: 1, b: 4 }], 4, 'hi'], ['hello', [['welcome', 10]], 11]]];
const output = deepFilterArray(input, function (e) { // this refers to the original array, so this.length=2 return typeof e === 'number' && e > this.length;});
/** * Yields: [[[3,[[4]],4],[[[10]],11]]] */console.log(JSON.stringify(output));
3. Counting filtered elements implementation
In both the variations above, we returned the new filtered array back. However, it might be asked to simply count and return the number of items which yields a turthy value for the callback function.
The implementation for this version remains almost the same, so I will highlight only the new changes made.
function deepFilterArray(arr, filterFn, ogArg = arr) { let count = 0;
if (!arr.length) { return count; }
arr.forEach((item) => { if (Array.isArray(item)) { count += deepFilterArray(item, filterFn, ogArg); } else { const isTruthy = filterFn.call(ogArg, item); if (isTruthy) { count++; } } });
return count;}
// Usageconst input = [1, [2, [3, [[4], { a: 1, b: 4 }], 4, 'hi'], ['hello', [['welcome', 10]], 11]]];
const output = deepFilterArray(input, function (e) { return typeof e === 'number' && e > this.length;});
// yields 5console.log(output);
Further Reading
I strongly encourage you to explore and tackle additional questions in my Recursion Questions for Frontend Interviews blog series.
By doing so, you can enhance your understanding and proficiency with recursion, preparing you to excel in your upcoming frontend interviews.
Wishing you best. Happy Interviewing 🫡.