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);

}
3
  • 1
    Not a duplicate: this specific question is about an unspecified depth, not about flattening an array of arrays. Commented Jul 13, 2016 at 11:03
  • The values in unflatten array could be non-numeric as well? Commented Jul 13, 2016 at 11:31
  • 1
    Check this answer from a similar question Commented Jul 13, 2016 at 11:39

9 Answers 9

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]]]]));

Sign up to request clarification or add additional context in comments.

2 Comments

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.
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.
2

You could use reduce:

function flatten( array ){
  return array.reduce( function (a, b){
    return a.concat( Array.isArray(b) ? flatten(b) : b );
  }, [] );
}

1 Comment

I see from your comment on another answer that flatten should accept non-array values. I modified the code here to return [] if the argument is not an array.
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);

1 Comment

You are the khallaghest developer I ever seeen. pashmaaam.
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));

2 Comments

Brilliant, but I just don't understand what you have written.
I've commented the code. I hope that will help you and I'm always available for further explanations ;)
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);

Comments

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]

Comments

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);
    }
}

Comments

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;
}

Comments

-1

Try this:

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

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

3 Comments

I was thinking that but the solution has to accept the empty object {} also :/
that is really a no go solution. because of the replace and finally with eval without emergency.
If the input is a string this would cause issues. say for example : [1, [2], 3, "[4]"]

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.