How to flatten array using Javascript

How to flatten array using Javascript

Problem

So you have some nested array but need to flattened it so you use it inside your codebase. There are actually a couple of ways to do it.

Here is what we are gonna take a look at;

  • Array.prototype.flat()
  • Reduce and Concat Solution
  • Recursive Solution
  • Stack Solution

1. Array.prototype.flat() Solution

The flat() method creates a new array with all sub-array elements concatenated into it recursively up to the specified depth.

  • Returns: A new array with the sub-array elements concatenated into it.
const arr1 = [0, 1, 2, [3, 4]];

console.log(arr1.flat());
// expected output: [0, 1, 2, 3, 4]

const arr2 = [0, 1, 2, [[[3, 4]]]];

// We can also give optional depth argument to flat function
console.log(arr2.flat(2));
// expected output: [0, 1, 2, [3, 4]]

Flat can also work on nested arrays

console.log(arr2.flat(Infinity))
// expected output: [0, 1, 2, 3, 4]

Or it can remove empty spots in the array

const arr5 = [1, 2, , 4, 5];
arr5.flat();
// [1, 2, 4, 5]

2. Reduce and Concat Solution

const flatten = (arr) => {
  return arr.reduce(function (flat, toFlatten) {
    return flat.concat(Array.isArray(toFlatten) 
            ? 
            flatten(toFlatten) 
            : toFlatten);
  }, []);
}

flatten([[1, 2, 3], [4, 5]]); // [1, 2, 3, 4, 5]
flatten([[[1, [1.1]], 2, 3], [4, 5]]); // [1, 1.1, 2, 3, 4, 5]

3. Recursive Solution

We can also apply recursive solution with the help of concat function

const flattenArray = (input) => {
  let result = []

  if (!Array.isArray(input)){
    return input
  }

  for (let data of input) {
    result = result.concat(flattenArray(data))
  }

  return result;
}

let arr = ["a", 0, [1, 2], 3, [[5, 6], [[8, 9]]]]

console.log(flattenArray(arr))
// ["a", 0, 1, 2, 3, 5, 6, 8, 9]

4. Stack Solution

We can also solve this by the help of stack data structure

// non recursive flatten deep using a stack
// note that depth control is hard/inefficient as we will need to tag EACH value with its own depth
// also possible w/o reversing on shift/unshift, but array OPs on the end tends to be faster
function flatten(input) {
  const stack = [...input];
  const res = [];
  while(stack.length) {
    // pop value from stack
    const next = stack.pop();
    if(Array.isArray(next)) {
      // push back array items, won't modify the original input
      stack.push(...next);
    } else {
      res.push(next);
    }
  }
  // reverse to restore input order
  return res.reverse();
}

const arr = [1, 2, [3, 4, [5, 6]]];
flatten(arr);
// [1, 2, 3, 4, 5, 6]