My first successful use of recursion!

I’ve just completed the Steamroller challenge from the JavaScript intermediate algorithms section and I’m pretty pumped. I was wondering if someone could answer a couple of questions about my code.

The challenge was to “flatten” all the items of an array of nested arrays into an array with only one depth. My solution (find below) was to cycle through the main array and check if each item was an array. If not, push it to a new arra (flatArr). If it was an array, cycle through it by calling the same function I used to cycle through the main one recursively (still pretty psyched I got it to work).

I have two question regarding my solution:

(1) I used a function within a function to avoid redeclaring my flatArr variable with each recursive iteration. Can you think of a way I could have avoided this and just used one single function?

(2) To avoid confusion, I used the same names for the function parameters and corresponding variables in each function throughout. In tutorials, I’ve noticed that function parameters usually have different names than the items that are passed. Is there a reason for this?

(3) Any other commentary/criticism would be appreciated. :slight_smile:

function steamrollArray(arr) {
  let flatArr = [];

  // Cycles through at array and pushes things that aren't arrays to new array
  function cycleThrough(arr, flatArr) {
    for (let i = 0; i < arr.length; i++) {

    // If item is an array, cycle through it. Must be done recursively.
      if (Array.isArray(arr[i])) {

        // Recusively cycle through
        cycleThrough(arr[i], flatArr)

        // If not an array, push to new array
      } else {
        flatArr.push(arr[i]);
      }
    }

    return flatArr;

  }

  return cycleThrough(arr, flatArr);
}
1 Like

I tested your code, and it is right. ^^. But I feel something not fine. I dont know why.
This is my solution, it is shorter and I just use one functions, you have two ones…

const flatten = (arr, initalValue = []) => {
   return arr.reduce(
       (acc, cur) => {
           if ( Array.isArray(cur) ) {
               return flatten(cur, acc)
           }
           return acc.concat(cur)
       }, initalValue
   )
}

// console.log(flatten([1, {}, [2], [3, [[4]]]]))
1 Like

It’s actually pretty common for a recursive function to be split out into two definitions: one that takes the minimal number of args, and a helper that takes the input state being passed around the stack that does the actual recursive work. Sometimes it’s done with just default args and one function, other times with two distinct functions like yours. And defining the helper as a nested function is definitely the right way to go.

In your case, you could have actually just inherited flatArr from the outer scope to use it as you do, but you’re still on to something. As an improvement, see if you can do it without mutating flatArr at all, but just by returning a new array in your recursive call.

1 Like

Challenge accepted! Thanks for the reply.

I’m not sure if this is what you had in mind, but I’ve managed to reduce it to one function.

let flatArr = [];

  // Cycles through array and pushes things that aren't arrays to new array (arr2)
function steamrollArray(arr, arr2) {
  for (let i = 0; i < arr.length; i++) {

  // If item is an array, cycle through it.
    if (Array.isArray(arr[i])) {

      // Recursive call
      steamrollArray(arr[i], arr2)

      // If not an array, push to new array
    } else {
      arr2.push(arr[i]);
    }
  }

  return arr2;

}

steamrollArray([1, [2], [3, [[4]]]], flatArr);