Last active
November 6, 2019 05:01
-
-
Save evanplaice/dd0a727ff0cc1397f33e3c00bec05d91 to your computer and use it in GitHub Desktop.
A collection of Array.flat() implementations in Javascript
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* eslint no-labels: 0 */ | |
/** | |
* Flattens an array of nested arrays using iteration w/ O(n) time complexity | |
* | |
* @param {Array} array input array | |
* @returns {Array} the flattened array | |
* | |
* @example | |
* const result = flatIterative([1, [2, [3, [4]]]]); | |
* console.log(result); | |
* > [1, 2, 3, 4] | |
*/ | |
function flatIterative (array) { | |
let start = 0; | |
const stack = []; | |
const idx = []; | |
const output = []; | |
outer: do { | |
inner: for (let i = start; i < array.length; i++) { | |
// handle arrays | |
if (Array.isArray(array[i])) { | |
// Edge Case: skip empty arrays | |
if (array[i].length === 0) { continue inner; } | |
stack.push([array, i]); // outer array goes on the stack | |
idx.push(i + 1); // mark next index of outer array | |
start = 0; // reset the start index | |
array = array[i]; // inner array gets traversed next | |
continue outer; // restart the array traversal | |
} | |
// handle values | |
output.push(array[i]); | |
} | |
// pop the stack if the top layer is done | |
array = stack.pop(); | |
start = idx.pop(); | |
} while (stack.length > 0); | |
return output; | |
} | |
module.exports = flatIterative; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const test = require('tape'); | |
const flat = require('./flat-iterative.js'); | |
test('flat(array) - should return an empty array if the input is empty', t => { | |
const expect = []; | |
const result = flat([]); | |
t.equal(Object.prototype.toString.call(result), '[object Array]', 'return type'); | |
t.equal(result.length, 0, 'output length'); | |
t.deepEqual(result, expect, 'output value'); | |
t.end(); | |
}); | |
test('flat(array) - an already flat array should return the same as the input', t => { | |
const expect = [1, 2, 3, 4, 5]; | |
const result = flat([1, 2, 3, 4, 5]); | |
t.equal(Object.prototype.toString.call(result), '[object Array]', 'return type'); | |
t.equal(result.length, 5, 'output length'); | |
t.deepEqual(result, expect, 'output value'); | |
t.end(); | |
}); | |
test('flat(array) - should flat multiple levels of nested arrays with ascending depth', t => { | |
const expect = [1, 2, 3, 4]; | |
const result = flat([1, [2, [3, [4]]]]); | |
t.equal(Object.prototype.toString.call(result), '[object Array]', 'return type'); | |
t.equal(result.length, 4, 'output length'); | |
t.deepEqual(result, expect, 'output value'); | |
t.end(); | |
}); | |
test('flat(array) - should flatten if the input includes empty arrays', t => { | |
const expect = [1, 3]; | |
const result = flat([1, [], 3, []]); | |
t.equal(Object.prototype.toString.call(result), '[object Array]', 'return type'); | |
t.equal(result.length, 2, 'output length'); | |
t.deepEqual(result, expect, 'output value'); | |
t.end(); | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Flattens an array of nested arrays using recursion | |
* | |
* @param {Array} array input array | |
* @returns {Array} the flattened array | |
* | |
* @example | |
* const result = flatRecursive([1, [2, [3, [4]]]]); | |
* console.log(result); | |
* > [1, 2, 3, 4] | |
*/ | |
function flatRecursive (array, output = []) { | |
array.forEach((item) => { | |
if (Array.isArray(item)) { | |
flatRecursive(item, output); | |
} else { | |
output.push(item); | |
} | |
}); | |
return output; | |
} | |
module.exports = flatRecursive; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const test = require('tape'); | |
const flat = require('./flat-recursive.js'); | |
test('flat(array) - should return an empty array if the input is empty', t => { | |
const expect = []; | |
const result = flat([]); | |
t.equal(Object.prototype.toString.call(result), '[object Array]', 'return type'); | |
t.equal(result.length, 0, 'output length'); | |
t.deepEqual(result, expect, 'output value'); | |
t.end(); | |
}); | |
test('flat(array) - an already flat array should return the same as the input', t => { | |
const expect = [1, 2, 3, 4, 5]; | |
const result = flat([1, 2, 3, 4, 5]); | |
t.equal(Object.prototype.toString.call(result), '[object Array]', 'return type'); | |
t.equal(result.length, 5, 'output length'); | |
t.deepEqual(result, expect, 'output value'); | |
t.end(); | |
}); | |
test('flat(array) - should flat multiple levels of nested arrays with ascending depth', t => { | |
const expect = [1, 2, 3, 4]; | |
const result = flat([1, [2, [3, [4]]]]); | |
t.equal(Object.prototype.toString.call(result), '[object Array]', 'return type'); | |
t.equal(result.length, 4, 'output length'); | |
t.deepEqual(result, expect, 'output value'); | |
t.end(); | |
}); | |
test('flat(array) - should flatten if the input includes empty arrays', t => { | |
const expect = [1, 3]; | |
const result = flat([[[1], [], 3], []]); | |
t.equal(Object.prototype.toString.call(result), '[object Array]', 'return type'); | |
t.equal(result.length, 2, 'output length'); | |
t.deepEqual(result, expect, 'output value'); | |
t.end(); | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Flattens an array of nested arrays | |
* | |
* @param {Array} array input array | |
* @param {Array} initial reducer initial state | |
* @returns {Array} the flattened array | |
* | |
* @example | |
* const result = flatReduce([1, [2, [3, [4]]]]); | |
* console.log(result); | |
* > [1, 2, 3, 4] | |
*/ | |
function flatReduce (array, initial = []) { | |
return array.reduce((acc, curr) => { | |
if (Array.isArray(curr)) { | |
acc = flatReduce(curr, acc); | |
} else { | |
acc.push(curr); | |
} | |
return acc; | |
}, initial); | |
} | |
module.exports = flatReduce; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const test = require('tape'); | |
const flat = require('./flat-reduce.js'); | |
test('flat(array) - should return an empty array if the input is empty', t => { | |
const expect = []; | |
const result = flat([]); | |
t.equal(Object.prototype.toString.call(result), '[object Array]', 'return type'); | |
t.equal(result.length, 0, 'output length'); | |
t.deepEqual(result, expect, 'output value'); | |
t.end(); | |
}); | |
test('flat(array) - an already flat array should return the same as the input', t => { | |
const expect = [1, 2, 3, 4, 5]; | |
const result = flat([1, 2, 3, 4, 5]); | |
t.equal(Object.prototype.toString.call(result), '[object Array]', 'return type'); | |
t.equal(result.length, 5, 'output length'); | |
t.deepEqual(result, expect, 'output value'); | |
t.end(); | |
}); | |
test('flat(array) - should flat multiple levels of nested arrays into one array', t => { | |
const expect = [1, 2, 3, 4]; | |
const result = flat([1, [2, [3, [4]]]]); | |
t.equal(Object.prototype.toString.call(result), '[object Array]', 'return type'); | |
t.equal(result.length, 4, 'output length'); | |
t.deepEqual(result, expect, 'output value'); | |
t.end(); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
The full prod-ready project repository is available @ https://github.com/evanplaice/flat-demo