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
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:
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
[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:
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:
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:
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):
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
Before:
[1, [2, 3], [4, 5]]
After (flat):
[1, 2, 3, 4, 5]
Deeper Nested: Multiple Levels
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
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.
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 levelflat(2)flattens two levelsflat(Infinity)flattens all levels
// 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.
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:
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
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:
// 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.
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:
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:
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.
let arr = [1, [2, 3, [4, 5]]];
// Expected: [1, 2, 3, 4, 5]
Solution using recursion:
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.
let arr = [1, [2, [3, [4, 5]]]];
flattenToDepth(arr, 2); // [1, 2, 3, [4, 5]]
Solution:
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.
let arr = [1, [2, 3, [4, 5]], 2];
// Expected: [3, 4, 5]
Solution:
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.
let arr = [1, [2, 3], [4, [5, 6]]];
// Expected:
// [
// { value: 1, path: [0] },
// { value: 2, path: [1, 0] },
// { value: 3, path: [1, 1] },
// ...
// ]
Solution:
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.
let arr = [1, [2, 3], [4, [5, 6]]];
// Expected: 21 (1+2+3+4+5+6)
Solution using recursion:
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:
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:
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:
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:
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:
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 flattenRecursion gives you full control and is common in interviews
reduce()combined with recursion works for more complex transformationsflatMap()flattens one level while transformingSpread 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 | GitHub | X (Twitter)




