# Array Flatten in JavaScript: Everything You Need to Know

## What Are Nested Arrays?

A normal array looks like this:

```js
const fruits = ["apple", "banana", "mango"];
```

A **nested array** is an array that contains other arrays as elements:

```js
const nested = [1, [2, 3], [4, [5, 6]]];
```

You'll run into nested arrays more often than you think — API responses, grouped data, tree structures, matrix representations. They're everywhere.

* * *

## Why Flattening Is Useful

Imagine you're building a shopping cart. Each category returns its own array of items:

```js
const electronics = ["laptop", "phone"];
const clothing    = ["shirt", "jeans"];
const food        = ["rice", "dal"];

const allItems = [electronics, clothing, food];
// [["laptop", "phone"], ["shirt", "jeans"], ["rice", "dal"]]
```

Now try looping over `allItems` to render each product — you'll get arrays, not strings. You need a **flat** list:

```js
// What you want
["laptop", "phone", "shirt", "jeans", "rice", "dal"]
```

That's exactly what flattening does — it takes a nested array and collapses it into a single-level array.

* * *

## The Concept: What "Flatten" Really Means

Think of nested arrays like Russian dolls. Flattening is opening each doll and laying everything out on a table.

```plaintext
Input:  [1, [2, 3], [4, [5, [6]]]]

Flatten 1 level:   [1, 2, 3, 4, [5, [6]]]
Flatten 2 levels:  [1, 2, 3, 4, 5, [6]]
Flatten fully:     [1, 2, 3, 4, 5, 6]
```

The **depth** controls how many levels deep you unwrap.

* * *

## Approach 1: `Array.flat()` — The Modern Way

ES2019 introduced `Array.flat()`. Clean, readable, built-in.

```js
const arr = [1, [2, 3], [4, [5, 6]]];

arr.flat();     // [1, 2, 3, 4, [5, 6]]  → default depth is 1
arr.flat(2);    // [1, 2, 3, 4, 5, 6]    → depth 2
```

### Flatten completely with `Infinity`

When you don't know how deeply nested the array is:

```js
const deep = [1, [2, [3, [4, [5]]]]];

deep.flat(Infinity); // [1, 2, 3, 4, 5]
```

### It also removes empty slots

```js
const sparse = [1, , 3, [4, , 6]];
sparse.flat(); // [1, 3, 4, 6]  ← empty slots removed
```

**When to use:** Modern browsers and Node.js 11+. This should be your default choice.

* * *

## Approach 2: `reduce()` + `concat()` — The Classic

Before `.flat()` existed, this was the go-to pattern. You'll see it in interviews a lot.

### Flatten one level deep

```js
function flattenOne(arr) {
  return arr.reduce((acc, val) => acc.concat(val), []);
}

flattenOne([1, [2, 3], [4, 5]]); // [1, 2, 3, 4, 5]
```

Step by step:

```plaintext
Start:       acc = []
Iteration 1: acc = [].concat(1)      → [1]
Iteration 2: acc = [1].concat([2,3]) → [1, 2, 3]
Iteration 3: acc = [1,2,3].concat([4,5]) → [1, 2, 3, 4, 5]
```

### Flatten recursively (any depth)

```js
function flattenDeep(arr) {
  return arr.reduce((acc, val) =>
    Array.isArray(val)
      ? acc.concat(flattenDeep(val))  // recurse if it's an array
      : acc.concat(val),              // otherwise just add it
  []);
}

flattenDeep([1, [2, [3, [4]]]]); // [1, 2, 3, 4]
```

* * *

## Approach 3: Spread + `concat()` — One-liner

```js
const arr = [1, [2, 3], [4, 5]];

[].concat(...arr); // [1, 2, 3, 4, 5]
```

This only works for **one level**. Using `...arr` spreads the outer array as arguments to `concat`, which handles the inner arrays.

> ⚠️ Breaks with deeply nested arrays or very large arrays (hits argument limit).

* * *

## Approach 4: Manual Recursion — Best for Interviews

Writing your own flatten from scratch is the most common interview question. Know this cold.

```js
function flatten(arr, depth = Infinity) {
  const result = [];

  for (const item of arr) {
    if (Array.isArray(item) && depth > 0) {
      // it's an array — go deeper
      result.push(...flatten(item, depth - 1));
    } else {
      // it's a value — add it
      result.push(item);
    }
  }

  return result;
}

flatten([1, [2, [3, [4]]]]);       // [1, 2, 3, 4]       ← full depth
flatten([1, [2, [3, [4]]]], 1);    // [1, 2, [3, [4]]]   ← 1 level
flatten([1, [2, [3, [4]]]], 2);    // [1, 2, 3, [4]]     ← 2 levels
```

* * *

## Approach 5: Stack-Based (No Recursion)

Recursion can hit the call stack limit with deeply nested arrays. A stack-based approach avoids that:

```js
function flattenIterative(arr) {
  const stack = [...arr];
  const result = [];

  while (stack.length) {
    const item = stack.pop();

    if (Array.isArray(item)) {
      stack.push(...item);  // push children back onto the stack
    } else {
      result.unshift(item); // add value to front (preserves order)
    }
  }

  return result;
}

flattenIterative([1, [2, [3, [4, 5]]]]); // [1, 2, 3, 4, 5]
```

This is great to mention in interviews when the interviewer asks *"what if the input is extremely deeply nested?"*

* * *

## Common Interview Scenarios

### Q1: Flatten only one level

```js
// Input:  [1, [2, 3], [4, [5]]]
// Output: [1, 2, 3, 4, [5]]

arr.flat();                           // built-in
arr.reduce((a, v) => a.concat(v), []); // manual
```

### Q2: Flatten completely

```js
// Input:  [1, [2, [3, [4, [5]]]]]
// Output: [1, 2, 3, 4, 5]

arr.flat(Infinity);   // built-in
flattenDeep(arr);     // recursive
```

### Q3: Flatten and then remove duplicates

```js
const arr = [[1, 2], [2, 3], [3, 4]];

const result = [...new Set(arr.flat())];
// [1, 2, 3, 4]
```

### Q4: Flatten an array of objects' nested arrays

```js
const data = [
  { id: 1, tags: ["js", "node"] },
  { id: 2, tags: ["react", "js"] },
];

const allTags = data.map(item => item.tags).flat();
// ["js", "node", "react", "js"]

// Or using flatMap (map + flat in one step):
const allTags2 = data.flatMap(item => item.tags);
// ["js", "node", "react", "js"]
```

### Q5: Count total elements after flattening (without flattening)

```js
function countElements(arr) {
  return arr.reduce((count, item) =>
    Array.isArray(item) ? count + countElements(item) : count + 1
  , 0);
}

countElements([1, [2, [3, 4]], 5]); // 5
```

* * *

## Quick Tip: `flatMap()` — Map and Flatten Together

`flatMap()` is equivalent to `.map().flat(1)` — super useful when your map callback returns arrays:

```js
const sentences = ["Hello World", "JavaScript is fun"];

// Without flatMap
sentences.map(s => s.split(" ")).flat();
// ["Hello", "World", "JavaScript", "is", "fun"]

// With flatMap
sentences.flatMap(s => s.split(" "));
// ["Hello", "World", "JavaScript", "is", "fun"]
```

* * *

## When to Use What

| Situation | Best Choice |
| --- | --- |
| Modern codebase, any depth | `arr.flat(Infinity)` |
| Specific depth needed | `arr.flat(n)` |
| Map + flatten in one step | `arr.flatMap()` |
| Interview, write from scratch | Recursive `flatten()` |
| Extremely deep nesting | Stack-based iterative |
| Legacy code / no ES2019 | `reduce()` + `concat()` |

* * *

## Summary

Flattening arrays is about **collapsing nested structure into a single level**. JavaScript gives you `.flat()` for everyday use, but knowing how to implement it manually — recursively or iteratively — is what separates a good developer from a great one.

The next time you see `[[1,2],[3,4]]` in an API response, you'll know exactly what to do. 🧩

* * *

*Found this useful? Share it with someone grinding LeetCode or preparing for their next JavaScript interview. 🚀*
