1

The problem is to try and remove nested arrays:

steamrollArray([1, [2], [3, [[4]]]]); // should return [1, 2, 3, 4]

I have tried this but the recursion is failing when a nested array appears.

function checkElement(el) {
    if (Array.isArray(el)) {
        if (el.length === 1) {
            return checkElement(el[0]); 
        } else {
            for (var i=0; i < el.length; i++){
                checkElement(el[i]); 
            }  
        }

    } else {
        return (el);    
    }   
}

function steamrollArray(arr) {
  var finalArr = [];
    for (var i=0; i < arr.length; i++){
        finalArr.push(checkElement(arr[i])); 
    }  


  return (finalArr);

}
JohnnyBizzle
  • 971
  • 3
  • 17
  • 31

9 Answers9

3

A proposal for the first part:

You could change the return value to array and use concat instead of push.

function checkElement(el) {
    // collect the values of the checked array
    var temp = [];
    if (Array.isArray(el)) {
        if (el.length === 1) {
            return checkElement(el[0]);
        } else {
            for (var i = 0; i < el.length; i++) {
                // collect the values
                temp = temp.concat(checkElement(el[i]));
            }
            // return flat values
            return temp;
        }
    } else {
        return el;
    }
}

// this can be shorten to
function steamrollArray(arr) {
    return checkElement(arr);
}

console.log(steamrollArray([1, [2], [3, [[4]]]]));

Part two, a bit shorter:

function steamrollArray(arr) {
    return arr.reduce(function flat(r, a) {
        return Array.isArray(a) && a.reduce(flat, r) || r.concat(a);
    }, []);
}

console.log(steamrollArray([1, [2], [3, [[4]]]]));
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
  • Thanks I understand the first solution and it passed the tests. The second one I don't follow though I'm sure it also works. If you add comments I might be able to follow it. – JohnnyBizzle Jul 13 '16 at 18:26
  • it simply uses Array#reduce with an empty array as start value and a callback which returns either if the element is an array, the values from the call on every element or the value itself. – Nina Scholz Jul 13 '16 at 18:39
2

You could use reduce:

function flatten( array ){
  return array.reduce( function (a, b){
    return a.concat( Array.isArray(b) ? flatten(b) : b );
  }, [] );
}
pishpish
  • 2,574
  • 15
  • 22
  • I see from your comment on another answer that `flatten` should accept non-array values. I modified the code [here](http://jsbin.com/pecipuzobo/edit?js,console) to return `[]` if the argument is not an array. – pishpish Jul 13 '16 at 12:31
2

I think this would be the funniest way to do this and also it's one line no more. Also it leaves extraction to native code which is much faster than Scripting.

var nestedArray = [1, [2], [3, [[4]]]];
var flatten = nestedArray.toString().split(',').map(Number);

console.log(flatten);
Morteza Tourani
  • 3,506
  • 5
  • 41
  • 48
1

You can use recursion like this:

function flatten(array) {
    var flat = []; //The result array
    //An IIFE that will perform the recursion,
    //is equivalent to: function rec(param) {.....}; rec(param);
    (function rec(a) {
        //For each element in the array:
        //If the element is an array then call the 'rec' function.
        //Else, push it to the result array.
        //I used the conditional (ternary) operator (condition ? expr1 : expr2 )
        for(var i in a) Array.isArray(a[i]) ? rec(a[i]) : flat.push(a[i]);
    })(array);//Initiate the recursion with the main array 
    return flat;//Return the final result
};

var a = [1, [2], [3, [[4]]]];


function flatten(array) {
    var flat = [];      
    (function rec(a) {
        for(var i in a) Array.isArray(a[i]) ? rec(a[i]) : flat.push(a[i]);
    })(array);        
    return flat;
};

console.log(flatten(a));
Ismail RBOUH
  • 10,292
  • 2
  • 24
  • 36
1

Using a generator function allows you to efficiently iterate through nested array elements without allocating unnecessary memory. If you really need the flattened array itself, use [...iterable] or Array.from(iterable):

function* deepIterate(array) {
  for (a of array) Array.isArray(a) ? yield* deepIterate(a) : yield a;
}

// Iterate through flattened array:
for (a of deepIterate([1,[2,[3]]])) console.log(a);

// Flatten array:
var flat = Array.from(deepIterate([1,[2,[3]]]));
console.log(flat);
le_m
  • 19,302
  • 9
  • 64
  • 74
0

You can't just return the values, or it wouldn't work when you have arrays of length > 1.

Here's a solution:

function steamrollArray(arr, flattened) {
    if (!flattened) flattened = [];
    for (var i=0; i < arr.length; i++){
         if (Array.isArray(arr[i])) {
             steamrollArray(arr[i], flattened);
         } else {
             flattened.push(arr[i]);
         }
    }  
    return flattened;
}

console.log(steamrollArray([1, [2], [3, [[4]]]])); // should return [1, 2, 3, 4]
Denys Séguret
  • 372,613
  • 87
  • 782
  • 758
0

Try This if it work for you

function steamrollArray(unflatenArr) {
    var flatenArr = [];
    if (Array.isArray(unflatenArr)) {
        for (var i = 0; i < unflatenArr.length; i++)
            arrFlat(unflatenArr[i], flatenArr);
    }
    return flatenArr;
}
function arrFlat(arr, refArr) {
    if (Array.isArray(arr)) {
        for (var i = 0; i < arr.length; i++) {
            arrFlat(arr[i], refArr);
        }
    }
    else {
        refArr.push(arr);
    }
}
Nitesh Shaw
  • 216
  • 2
  • 17
0

A simpler solution without using any recursion is by using splice method of Arrays. It works for any level of nesting.

function flattenArray(arr){

  for(var i=0;i<arr.length;i++){

    if(arr[i] instanceof Array){

      Array.prototype.splice.apply(arr,[i,1].concat(arr[i]))
       i--;
    }

  }

  return arr;
}
Pratik Barasia
  • 561
  • 1
  • 3
  • 14
-1

Try this:

function steamrollArray(unflatenArr){
    return eval("["+(JSON.stringify(unflatenArr).replace(/\[/g,'').replace(/\]/g,''))+"]")
}

steamrollArray([1, [2], [3, [[4]]]]);
Ismail RBOUH
  • 10,292
  • 2
  • 24
  • 36
Nitesh Shaw
  • 216
  • 2
  • 17