8

Good day!

Task would be to get a flat version of an array, that may include some amount of nested arrays as well as other elements. For input [1, [2], [3, [[4]]]] output [1, 2, 3, 4] expected. FreeCodeCamp spoiler alert. Naturally, recursive solution comes to mind, e.g.:

function steamrollArray(arr) {
  var result = [];
  for(var i = 0; i < arr.length; i++){
      //part of interest
      if (Array.isArray(arr[i])){
        var nestedElements = steamrollArray(arr[i]);
        for(var j = 0; j < nestedElements.length; j ++){
          result.push(nestedElements[j]);
        }
      //</part of interest>.
      } else {
        console.log("pushing: " + arr[i]);
        result.push(arr[i]);
      }
  }
  return result;
}

And it does it's thing. Result of sample run would be:

pushing: 1
pushing: 2
pushing: 3
pushing: 4
[1, 2, 3, 4]

And the question is: what goes awry, when we use concat to add nestedElements (that supposedly store return result of recursive call). If we are to change first if{} block in for loop (marked as part of interest) with snippet below:

if (Array.isArray(arr[i])){
    var nestedElements = steamrollArray(arr[i]);
    result.concat(nestedElements);
} else {

we will observe the following result:

pushing: 1
pushing: 2
pushing: 3
pushing: 4
[1]

My understanding was to pass the result of each recursive call to the concat function, which will add the returned array to the result, but for some reason it's not the case. Questions on this task was asked, like this one, but those concerned with the flattening algorithm part, which is not questioned here. I still fail to see the answer what exactly causes the difference. It very well might be something I simply overlooked in a hassle or as a result of my limited experience. Sorry if that's the case.

Community
  • 1
  • 1
shimey
  • 83
  • 1
  • 6
  • 2
    Array.concat will create a new array and append the elements to it and the result is a brand new array. Array.concat is immutable, Array.push is mutable. You might have to store the result of concat operation to nestedElements again. – Dhananjaya Kuppu Sep 02 '16 at 08:09
  • My lesson here I guess is to double check specification of tools I use, especially when it is so obvious that exact line of code causes the unexpected behaviour. Thanks you for your help! – shimey Sep 02 '16 at 08:29

3 Answers3

8

Array#concat returns a new array with the result.

The concat() method returns a new array comprised of the array on which it is called joined with the array(s) and/or value(s) provided as arguments.

So you need to assign the result:

result = result.concat(nestedElements);
// ^^^^^^ assignment
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
3

I am puzzled by the accepted answer as it can only concat two arrays. What you want for a nested array is actually:

var flatArray = [].concat.apply([], yourNestedArray);
KingOfHypocrites
  • 9,316
  • 9
  • 47
  • 69
0

this is my function.

   function _recursive_array_flat( ...args )
   {
       var _ret_array = [];
       for( _arg of args )
       {
           if ( _arg instanceof Array )
           {
               if ( _arg.length > 0 ) // work with consistent elements only
               _ret_array = _ret_array.concat( _recursive_array_flat( ..._arg ) );
           }
           else _ret_array.push( _arg );
       }

       return _ret_array;
    }

    var _ret = _recursive_array_flat( [0], 1,2,3, [ 4,5,6, [ 7,8,9 ] ] );
    console.log( _ret );
Dharman
  • 30,962
  • 25
  • 85
  • 135
Sandro Rosa
  • 507
  • 4
  • 12