Skip to content

Instantly share code, notes, and snippets.

@carloslfu
Created November 20, 2019 18:01
Show Gist options
  • Save carloslfu/25f7f3cb1ec328fa575a2918c1e725ba to your computer and use it in GitHub Desktop.
Save carloslfu/25f7f3cb1ec328fa575a2918c1e725ba to your computer and use it in GitHub Desktop.
Flatten an array in TypeScript
import { flatten, flattenShort } from "./flatten";
describe("flatten tests (iterative implementation)", () => {
it("should work well with flat arrays", () => {
const actual = flatten([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
const expected = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
expect(actual).toEqual(expected);
});
it("should flatten arbitrary nested arrays", () => {
const actual = flatten([[1, 2, [3]], 4]);
const expected = [1, 2, 3, 4];
expect(actual).toEqual(expected);
});
});
describe("flattenShort tests (recursive implementation)", () => {
it("should work well with flat arrays", () => {
const actual = flattenShort([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
const expected = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
expect(actual).toEqual(expected);
});
it("should flatten arbitrary nested arrays", () => {
const actual = flattenShort([[1, 2, [3]], 4]);
const expected = [1, 2, 3, 4];
expect(actual).toEqual(expected);
});
});
/* Once TypeScript releases recursive types https://github.com/microsoft/TypeScript/pull/33050
we could implement the NestedIntegerArray as follows:
export type NestedIntegerArray = Array<number | NestedIntegerArray>;
*/
export type NestedIntegerArray = Array<any>;
/**
* Flatten an array of arbitrarily nested arrays of integers into a flat array of integers (iterative implementation).
*
* @typedef {Array<number|NestedIntegerArray>} NestedIntegerArray
* @param {NestedIntegerArray} arr - An array of arbitrarily nested arrays of integers
* @return {Array<number>} A flat array of integers
*
* @example
*
* flatten([[1,2,[3]],4]) -> [1,2,3,4]
*/
export function flatten(arr: NestedIntegerArray): Array<number> {
let result = [];
let stack = [arr];
let indexes = [0];
while (stack.length > 0) {
let current = stack.pop();
let currentIndex = indexes.pop();
for (let i = currentIndex, len = current.length; i < len; i++) {
let element = current[i];
if (Array.isArray(element)) {
stack.push(current, element);
indexes.push(i + 1, 0);
break;
} else {
result.push(element);
}
}
}
return result;
}
/**
* Flatten an array of arbitrarily nested arrays of integers into a flat array of integers (recursive implementation).
*
* @typedef {Array<number|NestedIntegerArray>} NestedIntegerArray
* @param {NestedIntegerArray} arr - An array of arbitrarily nested arrays of integers
* @return {Array<number>} A flat array of integers
*
* @example
*
* flattenShort([[1,2,[3]],4]) -> [1,2,3,4]
*/
export function flattenShort(arr: NestedIntegerArray): Array<number> {
return arr.reduce(
(acc: Array<number>, val) =>
acc.concat(Array.isArray(val) ? flattenShort(val) : val),
[]
) as Array<number>;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment