From ae69076d3c5ffb473702a06c59584733b25bf64b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gromit=20=28=EC=A0=84=EB=AF=BC=EC=9E=AC=29?= <64779472+ssi02014@users.noreply.github.com> Date: Fri, 12 Jul 2024 09:56:21 +0900 Subject: [PATCH] feat(flattenDeep): add flattenDeep function (#160) --- benchmarks/flattenDeep.bench.ts | 27 ++++++++++++++++++++++ docs/.vitepress/en.mts | 1 + docs/.vitepress/ko.mts | 1 + docs/ko/reference/array/flatten.md | 8 +++---- docs/ko/reference/array/flattenDeep.md | 31 ++++++++++++++++++++++++++ docs/reference/array/flatten.md | 8 +++---- docs/reference/array/flattenDeep.md | 31 ++++++++++++++++++++++++++ src/array/flattenDeep.spec.ts | 18 +++++++++++++++ src/array/flattenDeep.ts | 28 +++++++++++++++++++++++ src/array/index.ts | 1 + 10 files changed, 146 insertions(+), 8 deletions(-) create mode 100644 benchmarks/flattenDeep.bench.ts create mode 100644 docs/ko/reference/array/flattenDeep.md create mode 100644 docs/reference/array/flattenDeep.md create mode 100644 src/array/flattenDeep.spec.ts create mode 100644 src/array/flattenDeep.ts diff --git a/benchmarks/flattenDeep.bench.ts b/benchmarks/flattenDeep.bench.ts new file mode 100644 index 00000000..96f2f27a --- /dev/null +++ b/benchmarks/flattenDeep.bench.ts @@ -0,0 +1,27 @@ +import { bench, describe } from 'vitest'; +import { flattenDeep as flattenDeepToolkit } from 'es-toolkit'; +import { flattenDeep as flattenDeepLodash } from 'lodash'; + +const createNestedArray = (values: number[]) => { + if (values.length === 0) { + return []; + } + const [first, ...rest] = values; + return [first, createNestedArray(rest)]; +}; + +describe('flattenDeep', () => { + const arr = createNestedArray(Array.from({ length: 30 }, (_, index) => index)); + + bench('es-toolkit/flattenDeep', () => { + flattenDeepToolkit(arr); + }); + + bench('lodash/flattenDeep', () => { + flattenDeepLodash(arr); + }); + + bench('js built-in/flat(Infinity)', () => { + arr.flat(Infinity); + }); +}); diff --git a/docs/.vitepress/en.mts b/docs/.vitepress/en.mts index 55608fa8..60540059 100644 --- a/docs/.vitepress/en.mts +++ b/docs/.vitepress/en.mts @@ -60,6 +60,7 @@ function sidebar(): DefaultTheme.Sidebar { { text: 'fill', link: '/reference/array/fill' }, { text: 'toFilled', link: '/reference/array/toFilled' }, { text: 'flatten', link: '/reference/array/flatten' }, + { text: 'flattenDeep', link: '/reference/array/flattenDeep' }, { text: 'forEachRight', link: '/reference/array/forEachRight' }, { text: 'groupBy', link: '/reference/array/groupBy' }, { text: 'intersection', link: '/reference/array/intersection' }, diff --git a/docs/.vitepress/ko.mts b/docs/.vitepress/ko.mts index 78b2198c..29255ccd 100644 --- a/docs/.vitepress/ko.mts +++ b/docs/.vitepress/ko.mts @@ -59,6 +59,7 @@ function sidebar(): DefaultTheme.Sidebar { { text: 'fill', link: '/ko/reference/array/fill' }, { text: 'toFilled', link: '/ko/reference/array/toFilled' }, { text: 'flatten', link: '/ko/reference/array/flatten' }, + { text: 'flattenDeep', link: '/ko/reference/array/flattenDeep' }, { text: 'forEachRight', link: '/reference/array/forEachRight' }, { text: 'groupBy', link: '/ko/reference/array/groupBy' }, { text: 'intersection', link: '/ko/reference/array/intersection' }, diff --git a/docs/ko/reference/array/flatten.md b/docs/ko/reference/array/flatten.md index 71af36ff..ea02f41d 100644 --- a/docs/ko/reference/array/flatten.md +++ b/docs/ko/reference/array/flatten.md @@ -22,14 +22,14 @@ function flatten(arr: T[], depth?: D): Array = T extends ReadonlyArray ? ExtractNestedArrayType : T; + +function flattenDeep(arr: T[]): Array>; +``` + +### 파라미터 + +- `arr` (`T[]`): 평탄화할 중첩 배열이에요. + +### 반환 값 + +(`Array>`): 모든 깊이가 평탄해진 새로운 배열이에요. + +## 예시 + +```typescript +const array = [1, [2, [3]], [4, [5, 6]]]; + +const result = flattenDeep(array); +// [1, 2, 3, 4, 5, 6]를 반환해요. +``` diff --git a/docs/reference/array/flatten.md b/docs/reference/array/flatten.md index f135f97b..3d95b99b 100644 --- a/docs/reference/array/flatten.md +++ b/docs/reference/array/flatten.md @@ -22,14 +22,14 @@ function flatten(arr: T[], depth?: D): Array = T extends ReadonlyArray ? ExtractNestedArrayType : T; + +function flattenDeep(arr: T[]): Array>; +``` + +### Parameters + +- `arr` (`T[]`): The array to flatten. + +### Returns + +(`Array>`): A new array with all depths flattened. + +## Examples + +```typescript +const array = [1, [2, [3]], [4, [5, 6]]]; + +const result = flattenDeep(array); +// Return [1, 2, 3, 4, 5, 6] +``` diff --git a/src/array/flattenDeep.spec.ts b/src/array/flattenDeep.spec.ts new file mode 100644 index 00000000..6c12f005 --- /dev/null +++ b/src/array/flattenDeep.spec.ts @@ -0,0 +1,18 @@ +import { describe, expect, it } from 'vitest'; +import { flattenDeep } from './flattenDeep'; + +describe('flattenDeep', () => { + it('should flatten a deeply nested array of numbers', () => { + const originArr = [1, [2, [3, [4, [5]]]]]; + const expectedArr = [1, 2, 3, 4, 5]; + + expect(flattenDeep(originArr)).toEqual(expectedArr); + }); + + it('should flatten a deeply nested array with mixed types', () => { + const originArr = [1, ['str', [3, [4, [false, [{ id: 1 }]]]]]]; + const expectedArr = [1, 'str', 3, 4, false, { id: 1 }]; + + expect(flattenDeep(originArr)).toEqual(expectedArr); + }); +}); diff --git a/src/array/flattenDeep.ts b/src/array/flattenDeep.ts new file mode 100644 index 00000000..ee70dd2d --- /dev/null +++ b/src/array/flattenDeep.ts @@ -0,0 +1,28 @@ +import { flatten } from './flatten'; + +/** + * Utility type for recursively unpacking nested array types to extract the type of the innermost element + * + * @example + * ExtractNestedArrayType<(number | (number | number[])[])[]> + * // number + * + * ExtractNestedArrayType<(boolean | (string | number[])[])[]> + * // string | number | boolean + */ +type ExtractNestedArrayType = T extends ReadonlyArray ? ExtractNestedArrayType : T; + +/** + * Flattens all depths of a nested array. + * + * @template T - The type of elements within the array. + * @param {T[]} arr - The array to flatten. + * @returns {Array>} A new array that has been flattened. + * + * @example + * const arr = flattenDeep([1, [2, [3]], [4, [5, 6]]]); + * // Returns: [1, 2, 3, 4, 5, 6] + */ +export function flattenDeep(arr: readonly T[]): Array> { + return flatten(arr, Infinity) as Array>; +} diff --git a/src/array/index.ts b/src/array/index.ts index 8e378807..192a2964 100644 --- a/src/array/index.ts +++ b/src/array/index.ts @@ -10,6 +10,7 @@ export { dropRightWhile } from './dropRightWhile.ts'; export { dropWhile } from './dropWhile.ts'; export { fill } from './fill.ts'; export { flatten } from './flatten.ts'; +export { flattenDeep } from './flattenDeep.ts'; export { forEachRight } from './forEachRight.ts'; export { groupBy } from './groupBy.ts'; export { intersection } from './intersection.ts';