Skip to content

Commit 5f9a3d9

Browse files
authored
Merge pull request #236 from xingarr/add_features_array_chapter
feat: add array manipulation utilities for chunking, flattening, deduplication and rotation
2 parents 930dc2b + 8c280ff commit 5f9a3d9

File tree

8 files changed

+1130
-0
lines changed

8 files changed

+1130
-0
lines changed

src/03-array/11-array-chunking.js

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
// src/03-array/11-array-chunking.js
2+
3+
/**
4+
* Array Chunking - Split an array into chunks of a specified size
5+
* Common use case: Pagination, batch processing, data visualization
6+
*/
7+
8+
// Approach 1: Using slice method
9+
function chunkArray(array, chunkSize) {
10+
if (chunkSize <= 0) {
11+
throw new Error('Chunk size must be greater than 0');
12+
}
13+
14+
const result = [];
15+
for (let i = 0; i < array.length; i += chunkSize) {
16+
result.push(array.slice(i, i + chunkSize));
17+
}
18+
return result;
19+
}
20+
21+
// Approach 2: Using splice method (modifies original array)
22+
function chunkArraySplice(array, chunkSize) {
23+
if (chunkSize <= 0) {
24+
throw new Error('Chunk size must be greater than 0');
25+
}
26+
27+
const result = [];
28+
const arrayCopy = [...array]; // Create a copy to avoid modifying original
29+
30+
while (arrayCopy.length > 0) {
31+
result.push(arrayCopy.splice(0, chunkSize));
32+
}
33+
return result;
34+
}
35+
36+
// Approach 3: Using reduce method (functional approach)
37+
function chunkArrayReduce(array, chunkSize) {
38+
if (chunkSize <= 0) {
39+
throw new Error('Chunk size must be greater than 0');
40+
}
41+
42+
return array.reduce((chunks, item, index) => {
43+
const chunkIndex = Math.floor(index / chunkSize);
44+
45+
if (!chunks[chunkIndex]) {
46+
chunks[chunkIndex] = []; // Start a new chunk
47+
}
48+
49+
chunks[chunkIndex].push(item);
50+
return chunks;
51+
}, []);
52+
}
53+
54+
// Examples
55+
console.log('=== Array Chunking Examples ===\n');
56+
57+
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
58+
console.log('Original array:', numbers);
59+
60+
console.log('\nChunk size 3 (slice method):', chunkArray(numbers, 3));
61+
// Output: [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]]
62+
63+
console.log('Chunk size 4 (splice method):', chunkArraySplice(numbers, 4));
64+
// Output: [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10]]
65+
66+
console.log('Chunk size 2 (reduce method):', chunkArrayReduce(numbers, 2));
67+
// Output: [[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]]
68+
69+
// Real-world example: Paginating data
70+
const users = [
71+
'Alice', 'Bob', 'Charlie', 'David', 'Eve',
72+
'Frank', 'Grace', 'Henry', 'Ivy', 'Jack'
73+
];
74+
75+
const itemsPerPage = 3;
76+
const pages = chunkArray(users, itemsPerPage);
77+
78+
console.log('\n=== Pagination Example ===');
79+
console.log(`Total users: ${users.length}`);
80+
console.log(`Items per page: ${itemsPerPage}`);
81+
console.log(`Total pages: ${pages.length}\n`);
82+
83+
pages.forEach((page, index) => {
84+
console.log(`Page ${index + 1}:`, page);
85+
});
86+
87+
// Edge cases
88+
console.log('\n=== Edge Cases ===');
89+
console.log('Empty array:', chunkArray([], 3));
90+
console.log('Chunk size larger than array:', chunkArray([1, 2], 5));
91+
console.log('Chunk size of 1:', chunkArray([1, 2, 3], 1));
92+
93+
// to see the output of this file use the command: node src/03-array/11-array-chunking.js

src/03-array/11-array-chunking.ts

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
// src/03-array/11-array-chunking.ts
2+
3+
/**
4+
* Array Chunking - Split an array into chunks of a specified size
5+
* Common use case: Pagination, batch processing, data visualization
6+
*/
7+
8+
// Approach 1: Using slice method
9+
function chunkArray<T>(array: T[], chunkSize: number): T[][] {
10+
if (chunkSize <= 0) {
11+
throw new Error('Chunk size must be greater than 0');
12+
}
13+
14+
const result: T[][] = [];
15+
for (let i = 0; i < array.length; i += chunkSize) {
16+
result.push(array.slice(i, i + chunkSize));
17+
}
18+
return result;
19+
}
20+
21+
// Approach 2: Using splice method (modifies original array)
22+
function chunkArraySplice<T>(array: T[], chunkSize: number): T[][] {
23+
if (chunkSize <= 0) {
24+
throw new Error('Chunk size must be greater than 0');
25+
}
26+
27+
const result: T[][] = [];
28+
const arrayCopy = [...array]; // Create a copy to avoid modifying original
29+
30+
while (arrayCopy.length > 0) {
31+
result.push(arrayCopy.splice(0, chunkSize));
32+
}
33+
return result;
34+
}
35+
36+
// Approach 3: Using reduce method (functional approach)
37+
function chunkArrayReduce<T>(array: T[], chunkSize: number): T[][] {
38+
if (chunkSize <= 0) {
39+
throw new Error('Chunk size must be greater than 0');
40+
}
41+
42+
return array.reduce((chunks: T[][], item: T, index: number) => {
43+
const chunkIndex = Math.floor(index / chunkSize);
44+
45+
if (!chunks[chunkIndex]) {
46+
chunks[chunkIndex] = []; // Start a new chunk
47+
}
48+
49+
chunks[chunkIndex].push(item);
50+
return chunks;
51+
}, []);
52+
}
53+
54+
// Examples
55+
console.log('=== Array Chunking Examples ===\n');
56+
57+
const numbers: number[] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
58+
console.log('Original array:', numbers);
59+
60+
console.log('\nChunk size 3 (slice method):', chunkArray(numbers, 3));
61+
// Output: [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]]
62+
63+
console.log('Chunk size 4 (splice method):', chunkArraySplice(numbers, 4));
64+
// Output: [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10]]
65+
66+
console.log('Chunk size 2 (reduce method):', chunkArrayReduce(numbers, 2));
67+
// Output: [[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]]
68+
69+
// Real-world example: Paginating data
70+
const users: string[] = [
71+
'Alice', 'Bob', 'Charlie', 'David', 'Eve',
72+
'Frank', 'Grace', 'Henry', 'Ivy', 'Jack'
73+
];
74+
75+
const itemsPerPage = 3;
76+
const pages = chunkArray(users, itemsPerPage);
77+
78+
console.log('\n=== Pagination Example ===');
79+
console.log(`Total users: ${users.length}`);
80+
console.log(`Items per page: ${itemsPerPage}`);
81+
console.log(`Total pages: ${pages.length}\n`);
82+
83+
pages.forEach((page, index) => {
84+
console.log(`Page ${index + 1}:`, page);
85+
});
86+
87+
// Edge cases
88+
console.log('\n=== Edge Cases ===');
89+
console.log('Empty array:', chunkArray([], 3));
90+
console.log('Chunk size larger than array:', chunkArray([1, 2], 5));
91+
console.log('Chunk size of 1:', chunkArray([1, 2, 3], 1));
92+
93+
// to see the output of this file use the command: node src/03-array/11-array-chunking.ts

src/03-array/12-flatten-arrays.js

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
// src/03-array/12-flatten-arrays.js
2+
3+
/**
4+
* Flatten Nested Arrays - Convert multi-dimensional arrays into a single-dimensional array
5+
* Common use case: Data processing, tree traversal results, nested data structures
6+
*/
7+
8+
// Approach 1: Using flat() method (ES2019+)
9+
function flattenSimple(array, depth = 1) {
10+
return array.flat(depth);
11+
}
12+
13+
// Approach 2: Deep flatten using flat(Infinity)
14+
function flattenDeep(array) {
15+
return array.flat(Infinity);
16+
}
17+
18+
// Approach 3: Recursive approach (custom implementation)
19+
function flattenRecursive(array) {
20+
const result = [];
21+
22+
for (let item of array) {
23+
if (Array.isArray(item)) {
24+
result.push(...flattenRecursive(item));
25+
} else {
26+
result.push(item);
27+
}
28+
}
29+
30+
return result;
31+
}
32+
33+
// Approach 4: Using reduce (functional approach)
34+
function flattenReduce(array) {
35+
return array.reduce((acc, item) => {
36+
return acc.concat(Array.isArray(item) ? flattenReduce(item) : item);
37+
}, []);
38+
}
39+
40+
// Approach 5: Iterative approach using stack
41+
function flattenIterative(array) {
42+
const stack = [...array];
43+
const result = [];
44+
45+
while (stack.length) {
46+
const item = stack.pop();
47+
48+
if (Array.isArray(item)) {
49+
stack.push(...item);
50+
} else {
51+
result.unshift(item); // Add to beginning since we're popping from end
52+
}
53+
}
54+
55+
return result;
56+
}
57+
58+
// Examples
59+
console.log('=== Flatten Arrays Examples ===\n');
60+
61+
const nestedArray = [1, [2, 3], [4, [5, 6]], [[[7]]], 8];
62+
console.log('Original nested array:', JSON.stringify(nestedArray));
63+
64+
console.log('\nFlat with depth 1:', flattenSimple(nestedArray, 1));
65+
// Output: [1, 2, 3, 4, [5, 6], [[7]], 8]
66+
67+
console.log('Flat with depth 2:', flattenSimple(nestedArray, 2));
68+
// Output: [1, 2, 3, 4, 5, 6, [7], 8]
69+
70+
console.log('Deep flatten (Infinity):', flattenDeep(nestedArray));
71+
// Output: [1, 2, 3, 4, 5, 6, 7, 8]
72+
73+
console.log('Recursive flatten:', flattenRecursive(nestedArray));
74+
// Output: [1, 2, 3, 4, 5, 6, 7, 8]
75+
76+
console.log('Reduce flatten:', flattenReduce(nestedArray));
77+
// Output: [1, 2, 3, 4, 5, 6, 7, 8]
78+
79+
console.log('Iterative flatten:', flattenIterative(nestedArray));
80+
// Output: [1, 2, 3, 4, 5, 6, 7, 8]
81+
82+
// Real-world example: Flattening category hierarchies
83+
console.log('\n=== Real-World Example: Category Hierarchy ===');
84+
85+
const categories = [
86+
'Electronics',
87+
['Computers', ['Laptops', 'Desktops', ['Gaming PCs', 'Workstations']]],
88+
['Mobile', ['Smartphones', 'Tablets']],
89+
'Books',
90+
['Fiction', ['Sci-Fi', 'Fantasy']]
91+
];
92+
93+
console.log('Original categories:', JSON.stringify(categories));
94+
console.log('Flattened categories:', flattenDeep(categories));
95+
96+
// Performance comparison
97+
console.log('\n=== Performance Comparison ===');
98+
99+
const largeNestedArray = [
100+
[1, 2, [3, 4]],
101+
[5, [6, [7, 8]]],
102+
[[9, 10], 11],
103+
[12, [13, [14, [15]]]]
104+
];
105+
106+
console.time('flat(Infinity)');
107+
flattenDeep(largeNestedArray);
108+
console.timeEnd('flat(Infinity)');
109+
110+
console.time('Recursive');
111+
flattenRecursive(largeNestedArray);
112+
console.timeEnd('Recursive');
113+
114+
console.time('Reduce');
115+
flattenReduce(largeNestedArray);
116+
console.timeEnd('Reduce');
117+
118+
console.time('Iterative');
119+
flattenIterative(largeNestedArray);
120+
console.timeEnd('Iterative');
121+
122+
// Edge cases
123+
console.log('\n=== Edge Cases ===');
124+
console.log('Empty array:', flattenDeep([]));
125+
console.log('Already flat array:', flattenDeep([1, 2, 3, 4]));
126+
console.log('Array with empty arrays:', flattenDeep([1, [], [2, []], 3]));
127+
console.log('Mixed types:', flattenDeep([1, 'hello', [true, [null, undefined]], { key: 'value' }]));
128+
129+
// to see the output of this file use the command: node src/03-array/12-flatten-arrays.js

0 commit comments

Comments
 (0)