0

First time posting. Sorry for bad formatting. I am trying to get my function to work. The current issue is that the recursion stops as soon as the recursive function is called for the first array element. I need it to keep going even after an array is called.

TLDR: I want to flatten the array.

function steamrollArray(arr) {
   var newArr=[];
   //return Array.isArray(arr[2]);

   //takes an array of which some elements will also be arrays and pushes its non-array elements to a new array (newArr)
   function recurseArr(a){
      for (i=0; i<a.length; i++){
         //recursion where you take the array element (also an array) and apply the same function until you get an element
         if(Array.isArray(a[i])){
            //&& i==a.length
            recurseArr(a[i]);
         }
         //case where the original array element is not an array but an element already
         else{
            newArr.push(a[i]);
         }
      }
   }
   //end of recurseArr

  recurseArr(arr);
  return newArr;
}

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

desired output: [1,2,2,3,2,4]

2 Answers2

1

You have two problems.

  1. You're mixing two styles of output. On the one hand, it looks like your functions return values. But on the other hand, it looks like the final output is supposed to come from newArr. In fact, the code is written mostly correctly, but you need to stick with the newArr paradigm and stop trying to return from the inner functions.

    Fix that like this:

    if(Array.isArray(a[i])){
       //&& i==a.length
       recurseArr(a[i]); // get rid of `return`
    }
    

    and this:

    return newArr; // remove this
    

    and this:

    // return recurseArr(arr); // don't do this
    recurseArr(arr);
    return newArr;
    
  2. You don't declare your counter variable i with var or let. This means it doesn't have function scope but is actually a member of the global scope, such as window in a browser or something else in Node, and thus you're modifying the same exact instance of i in each loop (as if you had declared var i before the outer function).

Making both these changes now yields (comments removed for easier understanding):

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

   function recurseArr(a) {
      for (let i = 0; i < a.length; i += 1) {
         if (Array.isArray(a[i])) {
            recurseArr(a[i]);
         }
         else {
            newArr.push(a[i]);
         }
      }
   }
   recurseArr(arr);
   return newArr;
}

Which works perfectly.

ErikE
  • 48,881
  • 23
  • 151
  • 196
  • It seems to be sending me into an infinite loop if I make those edits. Should I also eliminate the return newArr inside the recursive function? – David Morales Mar 01 '17 at 05:10
  • Yes that's right. Try removing that as well. – ErikE Mar 01 '17 at 05:50
  • Also, dont I need some kind of return inside my recursive function? Otherwise the output will just be undefined, right? – David Morales Mar 01 '17 at 06:08
  • See my update and you will figure it out. – ErikE Mar 01 '17 at 06:18
  • Thank you so much for taking your time on this. People like you truly help new coders learn. – David Morales Mar 01 '17 at 06:30
  • It's important for you to understand the concept of variable scope, especially in JavaScript (because it's so easy in that language to do exactly as you did, and accidentally end up with global variables when you wanted local ones). I suggest you go search for this and study up on what variable scope means! – ErikE Mar 01 '17 at 06:31
0

The main problem is with the return statement inside of your loop. The return statement exits your for loop.

If your main intent is to flatten the array, you are better off using a utility library like lodash or ramda, where flattening is just a:

R.flatten([1, 2, [2, 3], 2, [[[4]]]])
jgr0
  • 697
  • 2
  • 6
  • 20
  • Thank you! Unfortunately, I need to create my own function with basic javascript (it's for a course). I eliminated the return inside my recursive function. But no matter what I've tried I cant get it to stop looping indefinitely. – David Morales Mar 01 '17 at 05:58
  • @DavidMorales I marked this question as a duplicate of [Merge/flatten an array of arrays in JavaScript](http://stackoverflow.com/questions/10865025/merge-flatten-an-array-of-arrays-in-javascript) – there are countless answers there that will help you with your goal – even one from yours truly. – Mulan Mar 01 '17 at 06:20
  • Except the link you are referring to is not what I'm trying to do exactly. My function takes an array which will have elements that are arrays themselves so a simple concat wont flatten the array. I'm also trying to figure out why my particular function is not working. I could just copy someone else's solution to this flatten problem but I want to know what I'm doing wrong. Thanks! – David Morales Mar 01 '17 at 06:25