DEV Community

Cover image for How to flatten an array using recursion in Javascript
Rohit Kumawat
Rohit Kumawat

Posted on • Updated on

How to flatten an array using recursion in Javascript

Problem statement: There is an array containing elements as an array and those array elements can contain other elements as an array and so on. Now we have to convert this input array to a flat array that contains elements but not an array of elements.

Example:
Input: [1,2,3,[4,5,[6,7]],8,[9,[10,11]]]
Output: [1,2,3,4,5,6,7,8,9,10,11]

Solution:

function flatten(arr) {
  let flattenArr = [];
  arr.forEach(el => {
    if(Array.isArray(el)){
      const result = flatten(el);
      result.forEach(el => flattenArr.push(el));
    } else {
      flattenArr.push(el);
    }
  });
  return flattenArr;
}

const input = [1,2,3,[4,5,[6,7]],8,[9,[10,11]]];
const output = flatten(input);

console.log(output);
Enter fullscreen mode Exit fullscreen mode

We have used recursion to solve this problem

Algorithm steps:

  • First, we iterate through the given array.
  • Then check each element:
    • if it is not an array then push the elements in an updated array.
    • if it is an array then again call the same function flatten() i.e. recursion. Then we will combine our updated array and return values of flatten() using the spread operator in ES6. This will keep flatting the updated array.

Thanks for reading. For more tech and F.R.I.E.N.D.S. discussion, let's connect on Twitter.

Discussion (10)

Collapse
pengeszikra profile image
Peter Vivo

Good solution, but maybe use .flat

[1,2,3,[4,5,[6,7]],8,[9,[10,11]]].flat() // [1,2,3,4,5,[6,7],8,9,[10,11]]
Enter fullscreen mode Exit fullscreen mode

flat parameter is recursion level:

[1,2,3,[4,5,[6,7]],8,[9,[10,11]]].flat(2) // [1,2,3,4,5,6,7,8,9,10,11]
Enter fullscreen mode Exit fullscreen mode
Collapse
ip127001 profile image
Rohit Kumawat Author

Thanks for reading the article and for this solution 🙌. Really appreciate it.
But yeah I covered this solution because it covers recursion as well.

Collapse
merri profile image
Vesa Piittinen • Edited on

The good old super compatible way to do it:

function flatten(array) {
    // only mutate what you own, thus create a new copy
    array = array.slice(0);
    for (i = 0; i < array.length; i++) {
        // Array.isArray(array[i])
        if (Object.prototype.toString.call(array[i]) === '[object Array]') {
            // replaces single item with all items from the array
            Array.prototype.splice.apply(array, [i, 1].concat(array[i--]));
        }
    }
    return array;
}
Enter fullscreen mode Exit fullscreen mode

This should work with pretty much any JavaScript engine released within last 20 years, and does it without recursion.

But as others are saying you should just use .flat() these days instead of reinventing the wheel.

Collapse
ip127001 profile image
Rohit Kumawat Author • Edited on

Thanks for reading the article and for this solution 🙌. Really appreciate it.
But yeah I covered this solution because it covers recursion as well.

Collapse
patarapolw profile image
Pacharapol Withayasakpunt
  • Why would you have unstructured data required to be flattened like that in the first place?
  • Classical solution for this would be using .reduce or an equivalent.
const flatten = (arr) => arr.reduce((prev, c) => [...prev, ...c], [])
Enter fullscreen mode Exit fullscreen mode

Then, for a more complex version.

const flatten = (arr) => arr.reduce((prev, c) => [...prev, Array.isArray(c) ? ...flatten(c) : c], [])
Enter fullscreen mode Exit fullscreen mode
Collapse
ashutoshbw314 profile image
Ashutosh Biswas

In the recursive version, JavaScript produces SyntaxError(It would be nice if it wouldn't) cause ternary operator does not allow spreading like this. We can solve it using spread operators if we really want to, but I've found concat requires a little less typing:

const flatten = (arr) => arr.reduce((prev, c) => prev.concat(Array.isArray(c) ? flatten(c) : c), [])
Enter fullscreen mode Exit fullscreen mode
Collapse
ip127001 profile image
Rohit Kumawat Author

Thanks for reading the post and for another solution. I just wanted to cover use cases of recursion.

Collapse
edouardsouan profile image
RWRFyZA

Hello ^^. Nice use of recursion !

For the sake of discussion, here is another solution using built-in methods of Array :

const input = [1,2,3,[4,5,[6,7]],8,[9,[10,11]]]

let output = input.reduce((flattenArr, el)=>{
  if(Array.isArray(el)){
    flattenArr = flattenArr.concat(el.flat(2))
  }else{
    flattenArr.push(el)
  }
  return flattenArr
}, [])

console.log(output)
Enter fullscreen mode Exit fullscreen mode

One could argue that if your input's data are nested to a higher level, you will have to adapt the flat() method accordingly, which is not an issue in your code.
But won't you be suppose to know the shape of the data you're working with ^^ ?

Thank you for your time and showing us that recursion is not terrifying !

Collapse
ip127001 profile image
Rohit Kumawat Author

Thanks for reading the article and for this solution 🙌. Really appreciate it. But yeah I covered this solution because it covers recursion as well.

Collapse
kernix13 profile image
Jim Kernicky

Yes you can use the flat() method but I was looking for a recursion solution - thanks a lot!