Let's solve freeCodeCamp's intermediate algorithm scripting challenge, 'Steamroller'.
Starter Code
function steamrollArray(arr) {
return arr;
}
steamrollArray([1, [2], [3, [[4]]]]);
Instructions
Flatten a nested array. You must account for varying levels of nesting.
Test Cases (& Rules)
-
steamrollArray([[["a"]], [["b"]]])
should return["a", "b"]
. -
steamrollArray([1, [2], [3, [[4]]]])
should return[1, 2, 3, 4]
. -
steamrollArray([1, [], [3, [[4]]]])
should return[1, 3, 4]
. -
steamrollArray([1, {}, [3, [[4]]]])
should return[1, {}, 3, 4]
. - Your solution should not use the
Array.prototype.flat()
orArray.prototype.flatMap()
methods.
Our Approach
After reading the instructions, starter code, and test cases more than once, this is what we're working with:
- Our function takes in one argument,
arr
, which is an array of subarrays (contains numbers, strings, objects). - We must return the array flattened (see test cases).
- Must do this without methods such as
flat()
orflatMap()
.
Looking at all the test cases, we have some interesting cases like [[4]]]
as an index in arr
. We need to go visit each index and remove them from an array, if they are in one.
The first thing I will do is create an empty array, to hold our new flattened array.
let flattened = [];
As we have to visit each index of arr
, I figured to use the method, map()
.
arr.map((val) => {
// more code coming
})
What are we going to do at each index though? There is another array method, isArray()
, to check if the value is an array or not. It will return true
or false
.
If the value in the index is not an array, we can add it into our new flattened
array.
arr.map((val) => {
if (!Array.isArray(val)) {
flattened.push(val);
}
else {
// see below
}
})
That is not too complex. For our else
statement, how are we handling the indexes which contain an array?
We can use the ...
operator in the else
statement on steamrollArray()
so it will be called and flatten the array each loop. This is a recursive fashion (I believe).
arr.map((val) => {
if (!Array.isArray(val)) {
flattened.push(val);
}
else {
flattened.push(...steamrollArray(val));
}
})
If our arr
is [[[1]], 2]
, our first val
is [[1]]
. It will not pass the if
statement since it is in an array so it will be evaluated by the else
statement. We're calling the same flattened.push
but not on the val
. We're pushing ...steamrollArray(val)
, which will run the function again but it flattens val
with each execution. Once it is out of the subarray, it will be pushed into flattened
.
Make sure to return flattened
.
Our Solution
function steamrollArray(arr) {
let flattened = [];
arr.map(val => {
if (!Array.isArray(val)) {
flattened.push(val);
}
else {
flattened.push(...steamrollArray(val));
}
})
return flattened;
}
Links & Resources
'Steamroller' Challenge on fCC
Thank you for reading!
Top comments (0)