# Array Flatten in JavaScript


Arrays can contain other arrays, which can contain even more arrays. This creates a nested structure that's powerful for organizing complex data, but sometimes you need to collapse it into a single flat list. Flattening arrays is a common task in real-world applications and a favorite interview question.

In this article we will cover what nested arrays are, why you'd flatten them, and the different approaches to do it effectively.

* * *

## What Are Nested Arrays?

A nested array is an array that contains other arrays as elements.

### Simple Example

```javascript
let simple = [1, 2, 3];
console.log(simple); // [1, 2, 3]

let nested = [1, [2, 3], 4];
console.log(nested); // [1, [2, 3], 4]
```

The difference: `nested` has an array `[2, 3]` as one of its elements.

### Deeply Nested Arrays

Arrays can be nested multiple levels deep:

```javascript
let deeplyNested = [
  1,
  [2, 3],
  [4, [5, 6]],
  [[7, 8], 9]
];
console.log(deeplyNested);
// [1, [2, 3], [4, [5, 6]], [[7, 8], 9]]
```

This creates a tree-like structure.

### Visualizing Nested Structure

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

     Array
      |
  ____|____
  |   |   |
  1   |   |
    __|__
    |   |
    2   3


    [4, [5, 6]]
         |
      ___|___
      |     |
      4     |
          __|__
          |   |
          5   6
```

Each nested array is a branch in the tree.

* * *

## Why Flatten Arrays?

### Real-World Scenarios

**1. Processing nested data from an API:**

```javascript
let apiResponse = [
  { id: 1, tags: ["javascript", "web"] },
  { id: 2, tags: ["python", "data"] },
  { id: 3, tags: ["javascript", "node"] }
];

// You want all tags in a single list
let allTags = apiResponse.map(item => item.tags);
console.log(allTags);
// [["javascript", "web"], ["python", "data"], ["javascript", "node"]]

// After flattening
console.log(allTags.flat());
// ["javascript", "web", "python", "data", "javascript", "node"]
```

**2. Combining results from multiple queries:**

```javascript
let results = [
  [user1, user2, user3],  // Results from database query 1
  [user4, user5],         // Results from database query 2
  [user6]                 // Results from database query 3
];

// You need all users in one array
let allUsers = results.flat();
// [user1, user2, user3, user4, user5, user6]
```

**3. Merging arrays from different sources:**

```javascript
let frontend = ["HTML", "CSS", "JavaScript"];
let backend = ["Node.js", "Express", "MongoDB"];
let devops = ["Docker", "AWS"];

let skills = [frontend, backend, devops];
console.log(skills.flat());
// ["HTML", "CSS", "JavaScript", "Node.js", "Express", "MongoDB", "Docker", "AWS"]
```

**4. Processing hierarchical data (trees, menus, categories):**

```javascript
let categories = [
  {
    name: "Electronics",
    subcategories: [
      { name: "Phones" },
      { name: "Laptops" }
    ]
  },
  {
    name: "Clothing",
    subcategories: [
      { name: "Men" },
      { name: "Women" }
    ]
  }
];

// You might need to flatten this for a dropdown list
```

* * *

## The Concept of Flattening

Flattening means taking a nested array and converting it into a single-level array.

### Simple Flat: One Level Deep

```plaintext
Before:
[1, [2, 3], [4, 5]]

After (flat):
[1, 2, 3, 4, 5]
```

### Deeper Nested: Multiple Levels

```plaintext
Before:
[1, [2, [3, 4]], 5]

After (flat one level):
[1, 2, [3, 4], 5]

After (flat all levels):
[1, 2, 3, 4, 5]
```

Notice how flatten can work one level at a time or go all the way.

### Visualization of Flattening Process

```plaintext
Step by step flattening:

Original:  [1, [2, 3], [4, [5, 6]]]

Step 1: Take out the nested arrays
        1,  2, 3,  4, [5, 6]

Step 2: Check each element. If it's an array, recurse
        1,  2, 3,  4, 5, 6

Result: [1, 2, 3, 4, 5, 6]
```

* * *

## Different Approaches to Flatten Arrays

### Approach 1: Using flat() Method

JavaScript has a built-in `flat()` method (ES2019). It's the simplest approach.

```javascript
let nested = [1, [2, 3], [4, [5, 6]]];

let flat1 = nested.flat();
console.log(flat1); // [1, 2, 3, 4, [5, 6]]

let flatAll = nested.flat(Infinity);
console.log(flatAll); // [1, 2, 3, 4, 5, 6]
```

The argument to `flat()` specifies depth:
- `flat(1)` flattens one level
- `flat(2)` flattens two levels
- `flat(Infinity)` flattens all levels

```javascript
// Example with different depths
let array = [1, [2, [3, [4, 5]]]];

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

### Approach 2: Recursion

When you need custom logic or need to flatten conditionally, recursion is powerful.

```javascript
function flattenRecursive(arr) {
  let result = [];
  
  for (let item of arr) {
    if (Array.isArray(item)) {
      // If it's an array, flatten it and add its elements
      result.push(...flattenRecursive(item));
    } else {
      // If it's not an array, just add it
      result.push(item);
    }
  }
  
  return result;
}

let nested = [1, [2, 3], [4, [5, 6]]];
console.log(flattenRecursive(nested)); // [1, 2, 3, 4, 5, 6]
```

**How it works step by step:**

```plaintext
flattenRecursive([1, [2, 3], [4, [5, 6]]])
  |
  ├─ 1 is not an array → push 1
  |
  ├─ [2, 3] is an array → recursively flatten
  |   ├─ 2 is not an array → push 2
  |   └─ 3 is not an array → push 3
  |
  └─ [4, [5, 6]] is an array → recursively flatten
      ├─ 4 is not an array → push 4
      └─ [5, 6] is an array → recursively flatten
          ├─ 5 is not an array → push 5
          └─ 6 is not an array → push 6

Result: [1, 2, 3, 4, 5, 6]
```

### Approach 3: Reduce and Spread Operator

```javascript
function flattenReduce(arr) {
  return arr.reduce((flat, item) => {
    return flat.concat(Array.isArray(item) ? flattenReduce(item) : item);
  }, []);
}

let nested = [1, [2, 3], [4, [5, 6]]];
console.log(flattenReduce(nested)); // [1, 2, 3, 4, 5, 6]
```

This combines `reduce()` for accumulation with recursion for nested arrays.

**Breaking it down:**

```javascript
// For each item:
// - If it's an array, recursively flatten and concat
// - If it's not, just concat the item itself

[1, [2, 3]]
  |
  ├─ 1: concat to [] → [1]
  └─ [2, 3]: flatten recursively, then concat → [1, 2, 3]
```

### Approach 4: Using flatMap (One Level Only)

`flatMap()` is like `map()` but automatically flattens the result one level.

```javascript
let nested = [[1, 2], [3, 4], [5, 6]];

let result = nested.flatMap(item => item);
console.log(result); // [1, 2, 3, 4, 5, 6]
```

Useful when you're both transforming and flattening:

```javascript
let words = ["hello world", "javascript rocks"];

let letters = words.flatMap(word => word.split(""));
console.log(letters);
// ["h", "e", "l", "l", "o", " ", "w", "o", "r", "l", "d", ...]
```

### Approach 5: Spread Operator Loop (Shallow Flatten)

To flatten one level deep repeatedly:

```javascript
let nested = [1, [2, [3, 4]]];

// First spread
nested = [].concat(...nested);
console.log(nested); // [1, 2, [3, 4]]

// Second spread
nested = [].concat(...nested);
console.log(nested); // [1, 2, 3, 4]
```

This is useful when you control how many levels to flatten.

* * *

## Comparison of Approaches

| Approach | Syntax | Depth Control | Browser Support | Use Case |
| --- | --- | --- | --- | --- |
| `flat()` | Simple | Built-in | Modern browsers | General purpose, simplest |
| Recursion | Manual | Full control | All browsers | Custom logic, interviews |
| `reduce()` | Functional | Full control | All browsers | Combining flatten with mapping |
| `flatMap()` | Simple | One level | Modern browsers | Transform + flatten together |
| Spread loop | Manual | Manual | All browsers | Shallow flatten repeatedly |

* * *

## Common Interview Scenarios

### Scenario 1: Flatten an Array (General Question)

**Question:** Flatten the following nested array without using the `flat()` method.

```javascript
let arr = [1, [2, 3, [4, 5]]];
// Expected: [1, 2, 3, 4, 5]
```

**Solution using recursion:**

```javascript
function flatten(arr) {
  const result = [];
  
  for (let item of arr) {
    if (Array.isArray(item)) {
      result.push(...flatten(item));
    } else {
      result.push(item);
    }
  }
  
  return result;
}

console.log(flatten([1, [2, 3, [4, 5]]])); // [1, 2, 3, 4, 5]
```

**Interviewer follow-ups:**
- "Can you do this without recursion?" (Use iterative approach with a stack)
- "What if the array has mixed types?" (Check type before recursing)
- "Can you flatten only to a certain depth?" (Add a depth parameter)

### Scenario 2: Flatten with Depth Limit

**Question:** Flatten an array to a specific depth.

```javascript
let arr = [1, [2, [3, [4, 5]]]];
flattenToDepth(arr, 2); // [1, 2, 3, [4, 5]]
```

**Solution:**

```javascript
function flattenToDepth(arr, depth) {
  if (depth === 0) return arr;
  
  const result = [];
  
  for (let item of arr) {
    if (Array.isArray(item)) {
      result.push(...flattenToDepth(item, depth - 1));
    } else {
      result.push(item);
    }
  }
  
  return result;
}

console.log(flattenToDepth([1, [2, [3, [4, 5]]]], 2));
// [1, 2, 3, [4, 5]]
```

### Scenario 3: Flatten and Filter

**Question:** Flatten an array and keep only numbers greater than 2.

```javascript
let arr = [1, [2, 3, [4, 5]], 2];
// Expected: [3, 4, 5]
```

**Solution:**

```javascript
function flattenAndFilter(arr, condition) {
  const result = [];
  
  for (let item of arr) {
    if (Array.isArray(item)) {
      result.push(...flattenAndFilter(item, condition));
    } else if (condition(item)) {
      result.push(item);
    }
  }
  
  return result;
}

console.log(flattenAndFilter([1, [2, 3, [4, 5]], 2], x => x > 2));
// [3, 4, 5]
```

### Scenario 4: Flatten and Preserve Structure Info

**Question:** Flatten an array but keep track of original indices.

```javascript
let arr = [1, [2, 3], [4, [5, 6]]];
// Expected: 
// [
//   { value: 1, path: [0] },
//   { value: 2, path: [1, 0] },
//   { value: 3, path: [1, 1] },
//   ...
// ]
```

**Solution:**

```javascript
function flattenWithPath(arr, path = []) {
  const result = [];
  
  for (let i = 0; i < arr.length; i++) {
    const item = arr[i];
    const currentPath = [...path, i];
    
    if (Array.isArray(item)) {
      result.push(...flattenWithPath(item, currentPath));
    } else {
      result.push({ value: item, path: currentPath });
    }
  }
  
  return result;
}

console.log(flattenWithPath([1, [2, 3], [4, [5, 6]]]));
```

### Scenario 5: Sum All Numbers in Nested Array

**Question:** Calculate the sum of all numbers in a nested array.

```javascript
let arr = [1, [2, 3], [4, [5, 6]]];
// Expected: 21 (1+2+3+4+5+6)
```

**Solution using recursion:**

```javascript
function sumNested(arr) {
  let sum = 0;
  
  for (let item of arr) {
    if (Array.isArray(item)) {
      sum += sumNested(item);
    } else {
      sum += item;
    }
  }
  
  return sum;
}

console.log(sumNested([1, [2, 3], [4, [5, 6]]])); // 21
```

**Alternative using flatten:**

```javascript
function sumNested(arr) {
  return arr.flat(Infinity).reduce((sum, num) => sum + num, 0);
}

console.log(sumNested([1, [2, 3], [4, [5, 6]]])); // 21
```

* * *

## Practice Assignment

Work through these problems:

**1. Basic Flatten:**

```javascript
let arr1 = [1, [2, 3], [4, [5, 6]]];

function flatten(arr) {
  // Write your solution here
}

console.log(flatten(arr1)); // [1, 2, 3, 4, 5, 6]
```

**2. Flatten with Depth:**

```javascript
let arr2 = [1, [2, [3, [4, 5]]]];

function flattenDepth(arr, depth) {
  // Write your solution here
}

console.log(flattenDepth(arr2, 2)); // [1, 2, 3, [4, 5]]
```

**3. Flatten and Transform:**

```javascript
let arr3 = [1, [2, 3], [4, [5, 6]]];

function flattenAndDouble(arr) {
  // Write your solution here
}

console.log(flattenAndDouble(arr3)); // [2, 4, 6, 8, 10, 12]
```

**4. Flatten Mixed Types:**

```javascript
let arr4 = [1, ["hello", 2], [true, [3, "world"]]];

function flattenNumbers(arr) {
  // Keep only numbers, flatten completely
}

console.log(flattenNumbers(arr4)); // [1, 2, 3]
```

Try implementing each without using the built-in `flat()` method.

* * *

## Quick Recap

* **Nested arrays** are arrays that contain other arrays as elements
  
* Flattening converts a nested array into a single-level array
  
* **Use cases:** Processing API responses, combining results from multiple sources, handling hierarchical data
  
* `flat()` method is the built-in solution (simplest to read)
  
* `flat(depth)` controls how many levels to flatten
  
* **Recursion** gives you full control and is common in interviews
  
* `reduce()` combined with recursion works for more complex transformations
  
* `flatMap()` flattens one level while transforming
  
* Spread operator can repeatedly flatten one level at a time
  
* Interview questions often ask you to flatten without the built-in method
  
* Think about edge cases: mixed types, depth limits, tracking structure information

Array flattening is both practical and a great way to practice recursion. Master these approaches and you'll handle nested data with confidence.

Happy coding! 🚀

---

> If you enjoyed this article, check out my other blogs on this profile.
> 🔗 Connect with me: [LinkedIn](https://linkedin.com/in/rajharsh03) | [GitHub](https://github.com/RajHarsh03) | [X (Twitter)](https://x.com/rajharsh03)
