DEV Community

Cover image for Array Flatten in JavaScript
Pratham
Pratham

Posted on

Array Flatten in JavaScript

Turning messy nested arrays into clean, flat ones — and understanding why it matters.


At some point, you'll run into an array that looks like this:

const data = [1, [2, 3], [4, [5, 6]], 7];
Enter fullscreen mode Exit fullscreen mode

Arrays inside arrays. Arrays inside arrays inside arrays. It's like opening a box and finding more boxes inside, and inside those boxes — even more boxes.

This is a nested array, and while they show up naturally in real-world data (think category trees, API responses, multi-level menus), they're a pain to work with when you just need a simple, flat list of values. That's where flattening comes in.

When I first encountered this concept in the ChaiCode Web Dev Cohort 2026, it seemed like a niche problem. But it kept showing up — in coding challenges, interview questions, and even real project scenarios. Let me walk you through it.


What Are Nested Arrays?

A nested array is simply an array that contains other arrays as elements. The "depth" of nesting refers to how many levels deep the arrays go.

// Depth 1 — arrays inside an array
const depth1 = [1, [2, 3], [4, 5]];

// Depth 2 — arrays inside arrays inside an array
const depth2 = [1, [2, [3, 4]], [5, [6]]];

// Depth 3 — you get the idea
const depth3 = [1, [2, [3, [4, 5]]]];
Enter fullscreen mode Exit fullscreen mode

Visual: Nested Array Structure

depth1:  [1, [2, 3], [4, 5]]

Level 0:  [ 1,  ┌──────┐,  ┌──────┐ ]
               │ 2, 3 │   │ 4, 5 │
               └──────┘   └──────┘

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

Level 0:  [ 1,  ┌──────────────┐,  ┌──────────┐ ]
               │ 2, ┌──────┐ │   │ 5, ┌───┐ │
               │    │ 3, 4 │ │   │    │ 6 │ │
               │    └──────┘ │   │    └───┘ │
               └──────────────┘   └──────────┘
Enter fullscreen mode Exit fullscreen mode

Nested arrays create a tree-like structure. The deeper the nesting, the harder it is to access and process individual values.

How Do Nested Arrays Happen?

They're more common than you'd think:

// Grouping data by category
const menu = [
  ["Pizza", "Burger", "Pasta"],
  ["Coke", "Juice", "Water"],
  ["Ice Cream", "Brownie"],
];

// API response with nested structures
const apiData = [
  { name: "Pratham", skills: ["JS", "React"] },
  { name: "Arjun", skills: ["Python", "Django"] },
];

// Matrix / grid data
const grid = [
  [1, 2, 3],
  [4, 5, 6],
  [7, 8, 9],
];
Enter fullscreen mode Exit fullscreen mode

Why Is Flattening Useful?

Flattening means converting a nested array into a single-level array where all values are at the same depth.

// Before (nested)
[1, [2, 3], [4, [5, 6]]]

// After (flattened)
[1, 2, 3, 4, 5, 6]
Enter fullscreen mode Exit fullscreen mode

But why would you want this?

1. Easier Iteration

Try running .map() or .filter() on a nested array — it doesn't reach the inner elements:

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

// This doesn't work as expected
const doubled = nested.map((item) => item * 2);
console.log(doubled); // [2, NaN, NaN]
// Arrays can't be multiplied by 2!
Enter fullscreen mode Exit fullscreen mode

Flatten first, then process:

const flat = nested.flat();
const doubled = flat.map((num) => num * 2);
console.log(doubled); // [2, 4, 6, 8, 10] ✅
Enter fullscreen mode Exit fullscreen mode

2. Combining Multiple Lists

// Multiple API pages returned separate arrays
const page1 = ["Item A", "Item B"];
const page2 = ["Item C", "Item D"];
const page3 = ["Item E"];

const allPages = [page1, page2, page3];
console.log(allPages); // [["Item A", "Item B"], ["Item C", "Item D"], ["Item E"]]

const allItems = allPages.flat();
console.log(allItems); // ["Item A", "Item B", "Item C", "Item D", "Item E"]
Enter fullscreen mode Exit fullscreen mode

3. Simplifying Data Before Searching

const categories = [
  ["JavaScript", "TypeScript"],
  ["React", "Vue", "Angular"],
  ["Node.js", "Express"],
];

// Can't do .includes() directly on nested arrays
console.log(categories.includes("React")); // false ❌

// Flatten first
console.log(categories.flat().includes("React")); // true ✅
Enter fullscreen mode Exit fullscreen mode

The Concept of Flattening — Step by Step

Let's trace what flattening does to a nested array, one level at a time:

Flatten One Level

Input:    [1, [2, 3], [4, [5, 6]], 7]

Step 1:    1 → stays as is (not an array)
Step 2:    [2, 3] → unwrap → 2, 3
Step 3:    [4, [5, 6]] → unwrap → 4, [5, 6]  (only one level!)
Step 4:    7 → stays as is

Result:   [1, 2, 3, 4, [5, 6], 7]
Enter fullscreen mode Exit fullscreen mode

Notice that [5, 6] is still nested. Flattening by one level only removes one layer of nesting. To go deeper, you either flatten multiple times or flatten completely.

Flatten All Levels (Deep Flatten)

Input:    [1, [2, 3], [4, [5, 6]], 7]

                    ↓ remove ALL nesting ↓

Result:   [1, 2, 3, 4, 5, 6, 7]
Enter fullscreen mode Exit fullscreen mode

Transformation Visual

NESTED:
┌───┬───────────┬─────────────────┬───┐
│ 1 │ ┌───┬───┐ │ ┌───┬─────────┐ │ 7 │
│   │ │ 2 │ 3 │ │ │ 4 │ ┌───┬───┐│ │   │
│   │ └───┴───┘ │ │   │ │ 5 │ 6 ││ │   │
│   │           │ │   │ └───┴───┘│ │   │
│   │           │ └───┴─────────┘ │   │
└───┴───────────┴─────────────────┴───┘

FLATTENED:
┌───┬───┬───┬───┬───┬───┬───┐
│ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │
└───┴───┴───┴───┴───┴───┴───┘

All values on the same level. No nesting. Clean and simple.
Enter fullscreen mode Exit fullscreen mode

Different Approaches to Flatten Arrays

JavaScript gives you several ways to flatten arrays. Let's go from simplest to most advanced.

Approach 1: Array.flat() — The Built-In Way

ES2019 introduced .flat(), and it's by far the easiest option.

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

// Flatten one level (default)
console.log(nested.flat()); // [1, 2, 3, 4, [5, 6]]

// Flatten two levels
console.log(nested.flat(2)); // [1, 2, 3, 4, 5, 6]

// Flatten ALL levels (no matter how deep)
console.log(nested.flat(Infinity)); // [1, 2, 3, 4, 5, 6]
Enter fullscreen mode Exit fullscreen mode
  • .flat() with no argument flattens one level
  • .flat(2) flattens two levels deep
  • .flat(Infinity) flattens everything, no matter how deeply nested
// Even crazy nesting:
const deep = [1, [2, [3, [4, [5, [6]]]]]];
console.log(deep.flat(Infinity)); // [1, 2, 3, 4, 5, 6]
Enter fullscreen mode Exit fullscreen mode

This is the approach you should use in 99% of cases. It's clean, readable, and built right into the language.

Approach 2: concat() + Spread — Flatten One Level

Before .flat() existed, this was a common pattern:

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

const flat = [].concat(...nested);
console.log(flat); // [1, 2, 3, 4, 5]
Enter fullscreen mode Exit fullscreen mode

How it works: ...nested spreads the outer array into individual arguments for concat(). Arrays get merged, non-arrays stay as-is. But this only works for one level of nesting.

// Doesn't work for deeper nesting
const deep = [1, [2, [3, 4]]];
console.log([].concat(...deep)); // [1, 2, [3, 4]] — inner array still nested
Enter fullscreen mode Exit fullscreen mode

Approach 3: reduce() + concat() — Flatten One Level

Another pre-.flat() pattern:

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

const flat = nested.reduce((acc, item) => acc.concat(item), []);
console.log(flat); // [1, 2, 3, 4, 5]
Enter fullscreen mode Exit fullscreen mode

For each element: if it's an array, concat merges it. If it's a value, concat appends it. The accumulator builds up the flat result step by step.

Approach 4: Recursion — Deep Flatten From Scratch

This is the approach that shows up in interviews. Can you write a flatten function yourself?

const deepFlat = (arr) => {
  const result = [];

  for (const item of arr) {
    if (Array.isArray(item)) {
      // If it's an array, recursively flatten it and add the results
      result.push(...deepFlat(item));
    } else {
      // If it's a regular value, just add it
      result.push(item);
    }
  }

  return result;
};

const nested = [1, [2, [3, [4, [5]]]]];
console.log(deepFlat(nested)); // [1, 2, 3, 4, 5]
Enter fullscreen mode Exit fullscreen mode

How the Recursion Works — Traced Step by Step

deepFlat([1, [2, [3, [4]]]])

 1 is not an array  push 1
 [2, [3, [4]]] IS an array  recurse:
     deepFlat([2, [3, [4]]])
       2 is not an array  push 2
       [3, [4]] IS an array  recurse:
           deepFlat([3, [4]])
             3 is not an array  push 3
             [4] IS an array  recurse:
                 deepFlat([4])
                   4 is not an array  push 4
                   return [4]
             push ...[ 4]  result: [3, 4]
             return [3, 4]
       push ...[3, 4]  result: [2, 3, 4]
       return [2, 3, 4]
 push ...[2, 3, 4]  result: [1, 2, 3, 4]

Final: [1, 2, 3, 4] 
Enter fullscreen mode Exit fullscreen mode

The function keeps calling itself whenever it finds an array, going deeper and deeper until it hits a regular value. Then the results bubble back up and get combined.

Approach 5: reduce() + Recursion — Compact Deep Flatten

A more concise recursive version:

const deepFlat = (arr) =>
  arr.reduce(
    (acc, item) =>
      Array.isArray(item) ? [...acc, ...deepFlat(item)] : [...acc, item],
    []
  );

console.log(deepFlat([1, [2, [3, [4]]]])); // [1, 2, 3, 4]
Enter fullscreen mode Exit fullscreen mode

Same logic, just packed into a reduce call. It's elegant but can be harder to read for beginners.

Approach Comparison

Approach Depth Readability Interview Use When to Use
.flat() Configurable ⭐⭐⭐⭐⭐ Mention it Production code — always
concat + spread 1 level ⭐⭐⭐⭐ Rarely Quick one-level flatten
reduce + concat 1 level ⭐⭐⭐ Sometimes Understanding reduce
Recursive function All levels ⭐⭐⭐⭐ ✅ Common Interviews & deep flatten
reduce + recursion All levels ⭐⭐ Sometimes Showing off conciseness

Common Interview Scenarios

Flattening arrays is a very popular interview topic. Here are the variations you're most likely to see:

Scenario 1: "Flatten This Array"

The most basic question. They give you a nested array and ask you to flatten it.

// Input
const input = [1, [2, 3], [4, [5, 6, [7]]]];

// Expected output
// [1, 2, 3, 4, 5, 6, 7]

// Your answer
console.log(input.flat(Infinity));
// Or write the recursive version to show understanding
Enter fullscreen mode Exit fullscreen mode

Tip: Mention .flat(Infinity) for production code, then offer to write the recursive version. This shows you know both the practical and the conceptual approach.

Scenario 2: "Flatten to a Specific Depth"

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

// Flatten to depth 1
console.log(arr.flat(1)); // [1, 2, [3, [4]]]

// Flatten to depth 2
console.log(arr.flat(2)); // [1, 2, 3, [4]]
Enter fullscreen mode Exit fullscreen mode

For the custom implementation:

const flatToDepth = (arr, depth = 1) => {
  if (depth === 0) return [...arr];

  return arr.reduce(
    (acc, item) =>
      Array.isArray(item)
        ? [...acc, ...flatToDepth(item, depth - 1)]
        : [...acc, item],
    []
  );
};

console.log(flatToDepth([1, [2, [3, [4]]]], 2)); // [1, 2, 3, [4]]
Enter fullscreen mode Exit fullscreen mode

Scenario 3: "Flatten and Remove Duplicates"

A combined problem — flatten first, then deduplicate:

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

const result = [...new Set(nested.flat(Infinity))];
console.log(result); // [1, 2, 3, 4, 5, 6]
Enter fullscreen mode Exit fullscreen mode

Scenario 4: "Flatten an Array of Objects"

Sometimes the "nesting" isn't arrays inside arrays — it's nested properties:

const departments = [
  { name: "Engineering", members: ["Pratham", "Arjun"] },
  { name: "Design", members: ["Priya", "Neha"] },
  { name: "Marketing", members: ["Rahul"] },
];

// Get a flat list of all members
const allMembers = departments.flatMap((dept) => dept.members);
console.log(allMembers); // ["Pratham", "Arjun", "Priya", "Neha", "Rahul"]
Enter fullscreen mode Exit fullscreen mode

.flatMap() is like .map() followed by .flat(1) — perfect for cases where each element maps to an array and you want the results merged.


Let's Practice: Hands-On Assignment

Part 1: Basic Flattening

const nested = [["a", "b"], ["c", "d"], ["e"]];

const flat = nested.flat();
console.log(flat); // ["a", "b", "c", "d", "e"]
Enter fullscreen mode Exit fullscreen mode

Part 2: Deep Flattening

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

console.log(deep.flat()); // [1, 2, [3, [4, [5]]]] — only one level
console.log(deep.flat(Infinity)); // [1, 2, 3, 4, 5] — all levels
Enter fullscreen mode Exit fullscreen mode

Part 3: Write Your Own Flatten Function

const myFlat = (arr) => {
  const result = [];

  for (const item of arr) {
    if (Array.isArray(item)) {
      result.push(...myFlat(item));
    } else {
      result.push(item);
    }
  }

  return result;
};

console.log(myFlat([1, [2, [3, [4]]]])); // [1, 2, 3, 4]
console.log(myFlat(["a", ["b", ["c", "d"]], "e"])); // ["a", "b", "c", "d", "e"]
Enter fullscreen mode Exit fullscreen mode

Part 4: Flatten + Process

const scores = [[85, 92], [78, 95], [88, 76]];

const allScores = scores.flat();
const average = allScores.reduce((sum, s) => sum + s, 0) / allScores.length;

console.log("All scores:", allScores); // [85, 92, 78, 95, 88, 76]
console.log("Average:", average.toFixed(1)); // "85.7"
Enter fullscreen mode Exit fullscreen mode

Key Takeaways

  1. Nested arrays are arrays inside arrays. They occur naturally in grouped data, API responses, and matrix-like structures.
  2. Flattening converts a nested array into a single-level array. Use .flat() for one level, .flat(depth) for a specific depth, and .flat(Infinity) for everything.
  3. .flat() is the standard approach for production code. It's clean, built-in, and handles any depth.
  4. Recursive flattening is the approach interviewers want to see. It demonstrates your understanding of recursion and Array.isArray().
  5. .flatMap() combines mapping and flattening — useful when each element maps to an array and you want a flat result.

Wrapping Up

Array flattening might seem like a niche topic, but it sits at the intersection of practical data manipulation and interview-ready problem solving. In real projects, .flat() handles it in one method call. In interviews, writing the recursive version shows you understand how arrays, iteration, and recursion work together.

I'm learning these patterns through the ChaiCode Web Dev Cohort 2026 under Hitesh Chaudhary and Piyush Garg, and flattening arrays was one of those "aha" moments where recursion finally made intuitive sense. If you're struggling with recursion, start here — it's one of the cleanest examples of a recursive problem.

Connect with me on LinkedIn or visit PrathamDEV.in. More articles coming as I keep building and learning.

Happy coding! 🚀


Written by Pratham Bhardwaj | Web Dev Cohort 2026, ChaiCode

Top comments (0)