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];
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]]]];
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 │ │
│ └──────┘ │ │ └───┘ │
└──────────────┘ └──────────┘
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],
];
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]
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!
Flatten first, then process:
const flat = nested.flat();
const doubled = flat.map((num) => num * 2);
console.log(doubled); // [2, 4, 6, 8, 10] ✅
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"]
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 ✅
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]
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]
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.
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]
-
.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]
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]
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
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]
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]
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] ✅
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]
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
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]]
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]]
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]
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"]
.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"]
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
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"]
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"
Key Takeaways
- Nested arrays are arrays inside arrays. They occur naturally in grouped data, API responses, and matrix-like structures.
-
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. -
.flat()is the standard approach for production code. It's clean, built-in, and handles any depth. -
Recursive flattening is the approach interviewers want to see. It demonstrates your understanding of recursion and
Array.isArray(). -
.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)