mirror of
https://github.com/toss/es-toolkit.git
synced 2024-11-30 18:23:22 +03:00
feat(flatten): add flatten (#147)
* feat(flatten): add faltten (#137) * fix: fix lint * fix: fix test code description * test(flatten): add test case * Update docs/ko/reference/array/flatten.md * Update docs/ko/reference/array/flatten.md * Update docs/ko/reference/array/flatten.md * Update docs/reference/array/flatten.md --------- Co-authored-by: Sojin Park <raon0211@gmail.com>
This commit is contained in:
parent
3c8d105900
commit
7c824629ee
27
benchmarks/flatten.bench.ts
Normal file
27
benchmarks/flatten.bench.ts
Normal file
@ -0,0 +1,27 @@
|
||||
import { bench, describe } from 'vitest';
|
||||
import { flatten as flattenToolkit } from 'es-toolkit';
|
||||
import { flattenDepth as flattenDepthLodash } from 'lodash';
|
||||
|
||||
const createNestedArray = (values: any[]) => {
|
||||
if (values.length === 0) {
|
||||
return [];
|
||||
}
|
||||
const [first, ...rest] = values;
|
||||
return [first, createNestedArray(rest)];
|
||||
};
|
||||
|
||||
describe('flatten', () => {
|
||||
const arr = createNestedArray(Array.from({ length: 30 }, (_, index) => index));
|
||||
|
||||
bench('es-toolkit/flatten', () => {
|
||||
flattenToolkit(arr, 30);
|
||||
});
|
||||
|
||||
bench('lodash/flattenDepth', () => {
|
||||
flattenDepthLodash(arr, 30);
|
||||
});
|
||||
|
||||
bench('js built-in/flat', () => {
|
||||
arr.flat(30);
|
||||
});
|
||||
});
|
@ -58,6 +58,7 @@ function sidebar(): DefaultTheme.Sidebar {
|
||||
{ text: 'dropRight', link: '/reference/array/dropRight' },
|
||||
{ text: 'dropRightWhile', link: '/reference/array/dropRightWhile' },
|
||||
{ text: 'fill', link: '/reference/array/fill' },
|
||||
{ text: 'flatten', link: '/reference/array/flatten' },
|
||||
{ text: 'forEachRight', link: '/reference/array/forEachRight' },
|
||||
{ text: 'groupBy', link: '/reference/array/groupBy' },
|
||||
{ text: 'intersection', link: '/reference/array/intersection' },
|
||||
|
@ -57,6 +57,7 @@ function sidebar(): DefaultTheme.Sidebar {
|
||||
{ text: 'dropRight', link: '/ko/reference/array/dropRight' },
|
||||
{ text: 'dropRightWhile', link: '/ko/reference/array/dropRightWhile' },
|
||||
{ text: 'fill', link: '/ko/reference/array/fill' },
|
||||
{ text: 'flatten', link: '/ko/reference/array/flatten' },
|
||||
{ text: 'forEachRight', link: '/reference/array/forEachRight' },
|
||||
{ text: 'groupBy', link: '/ko/reference/array/groupBy' },
|
||||
{ text: 'intersection', link: '/ko/reference/array/intersection' },
|
||||
|
35
docs/ko/reference/array/flatten.md
Normal file
35
docs/ko/reference/array/flatten.md
Normal file
@ -0,0 +1,35 @@
|
||||
# flatten
|
||||
|
||||
중첩된 배열을 원하는 깊이까지 풀어서 평탄화해요.
|
||||
|
||||
JavaScript 언어에 포함된 [Array#flat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flat)과 동일하게 동작하지만, 더 빨라요.
|
||||
|
||||
## 인터페이스
|
||||
|
||||
```typescript
|
||||
function flatten<T, D extends number = 1>(arr: T[], depth?: D): Array<FlatArray<T[], D>>;
|
||||
```
|
||||
|
||||
### 파라미터
|
||||
|
||||
- `arr` (`T[]`): 평탄화할 중첩 배열이에요.
|
||||
- `depth` (`D`): 평탄화할 깊이에요. 기본값은 1이에요.
|
||||
|
||||
### 반환 값
|
||||
|
||||
(`Array<FlatArray<T[], D>>`): 원하는 깊이까지 평탄해진 새로운 배열이에요.
|
||||
|
||||
## 예시
|
||||
|
||||
```typescript
|
||||
const originArr = [1, [2, 3], [4, [5, 6]]];
|
||||
|
||||
const array1 = flatten(originArr);
|
||||
// [1, 2, 3, 4, [5, 6]]를 반환해요.
|
||||
|
||||
const array2 = flatten(originArr, 1);
|
||||
// [1, 2, 3, 4, [5, 6]]를 반환해요.
|
||||
|
||||
const array3 = flatten(originArr, 2);
|
||||
// [1, 2, 3, 4, 5, 6]를 반환해요.
|
||||
```
|
35
docs/reference/array/flatten.md
Normal file
35
docs/reference/array/flatten.md
Normal file
@ -0,0 +1,35 @@
|
||||
# flatten
|
||||
|
||||
Flattens the nested array given as an argument to the desired depth.
|
||||
|
||||
It works the same as [Array.prototype.flat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flat) provided by default in JavaScript and returns the same type. However, its performance is superior.
|
||||
|
||||
## Signature
|
||||
|
||||
```typescript
|
||||
function flatten<T, D extends number = 1>(arr: T[], depth?: D): Array<FlatArray<T[], D>>;
|
||||
```
|
||||
|
||||
### Parameters
|
||||
|
||||
- `arr` (`T[]`): The array to flatten.
|
||||
- `depth` (`D`): The depth to flatten, which defaults to 1.
|
||||
|
||||
### Returns
|
||||
|
||||
(`Array<FlatArray<T[], D>>`) A new array that has been flattened.
|
||||
|
||||
## Examples
|
||||
|
||||
```typescript
|
||||
const originArr = [1, [2, 3], [4, [5, 6]]];
|
||||
|
||||
const array1 = flatten(originArr);
|
||||
// Return [1, 2, 3, 4, [5, 6]]
|
||||
|
||||
const array2 = flatten(originArr, 1);
|
||||
// Return [1, 2, 3, 4, [5, 6]]
|
||||
|
||||
const array3 = flatten(originArr, 2);
|
||||
// Return [1, 2, 3, 4, 5, 6]
|
||||
```
|
63
src/array/flatten.spec.ts
Normal file
63
src/array/flatten.spec.ts
Normal file
@ -0,0 +1,63 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { flatten } from '.';
|
||||
|
||||
describe('flatten', () => {
|
||||
const originArr = [1, [2, [3, [4]]]];
|
||||
|
||||
it('should flatten a array to the default depth of 1', () => {
|
||||
const expectedArr = [1, 2, [3, [4]]];
|
||||
|
||||
expect(flatten(originArr)).toEqual(expectedArr);
|
||||
expect(originArr.flat()).toEqual(expectedArr);
|
||||
});
|
||||
|
||||
it('should flatten a deeply nested array to the specified depth', () => {
|
||||
const expectedArr1 = [1, 2, [3, [4]]];
|
||||
expect(flatten(originArr, 1)).toEqual(expectedArr1);
|
||||
expect(originArr.flat(1)).toEqual(expectedArr1);
|
||||
|
||||
const expectedArr2 = [1, 2, 3, [4]];
|
||||
expect(flatten(originArr, 2)).toEqual(expectedArr2);
|
||||
expect(originArr.flat(2)).toEqual(expectedArr2);
|
||||
|
||||
const expectedArr3 = [1, 2, 3, 4];
|
||||
expect(flatten(originArr, 3)).toEqual(expectedArr3);
|
||||
expect(originArr.flat(3)).toEqual(expectedArr3);
|
||||
|
||||
expect(flatten(originArr, Infinity)).toEqual(expectedArr3);
|
||||
expect(originArr.flat(Infinity)).toEqual(expectedArr3);
|
||||
});
|
||||
|
||||
it('should return the same array if depth is 0 or NaN or negative', () => {
|
||||
const expectedArr = [1, [2, [3, [4]]]];
|
||||
|
||||
expect(flatten(originArr, 0)).toEqual(expectedArr);
|
||||
expect(originArr.flat(0)).toEqual(expectedArr);
|
||||
|
||||
expect(flatten(originArr, NaN)).toEqual(expectedArr);
|
||||
expect(originArr.flat(NaN)).toEqual(expectedArr);
|
||||
|
||||
expect(flatten(originArr, -1)).toEqual(expectedArr);
|
||||
expect(originArr.flat(-1)).toEqual(expectedArr);
|
||||
});
|
||||
|
||||
it('should flatten arrays to the specified depth considering floating point values', () => {
|
||||
const expectedArr1 = [1, 2, [3, [4]]];
|
||||
expect(flatten(originArr, 1.3)).toEqual(expectedArr1);
|
||||
expect(originArr.flat(1.3)).toEqual(expectedArr1);
|
||||
|
||||
const expectedArr2 = [1, 2, 3, [4]];
|
||||
expect(flatten(originArr, 2.5)).toEqual(expectedArr2);
|
||||
expect(originArr.flat(2.5)).toEqual(expectedArr2);
|
||||
|
||||
const expectedArr3 = [1, 2, 3, 4];
|
||||
expect(flatten(originArr, 3.9)).toEqual(expectedArr3);
|
||||
expect(originArr.flat(3.9)).toEqual(expectedArr3);
|
||||
});
|
||||
|
||||
it('should handle empty array', () => {
|
||||
const originArr: number[] = [];
|
||||
|
||||
expect(flatten(originArr, 2)).toEqual([]);
|
||||
});
|
||||
});
|
33
src/array/flatten.ts
Normal file
33
src/array/flatten.ts
Normal file
@ -0,0 +1,33 @@
|
||||
/**
|
||||
* Flattens an array up to the specified depth.
|
||||
*
|
||||
* @template T - The type of elements within the array.
|
||||
* @template D - The depth to which the array should be flattened.
|
||||
* @param {T[]} arr - The array to flatten.
|
||||
* @param {D} depth - The depth level specifying how deep a nested array structure should be flattened. Defaults to 1.
|
||||
* @returns {Array<FlatArray<T[], D>>} A new array that has been flattened.
|
||||
*
|
||||
* @example
|
||||
* const arr = flatten([1, [2, 3], [4, [5, 6]]], 1);
|
||||
* // Returns: [1, 2, 3, 4, [5, 6]]
|
||||
*
|
||||
* const arr = flatten([1, [2, 3], [4, [5, 6]]], 2);
|
||||
* // Returns: [1, 2, 3, 4, 5, 6]
|
||||
*/
|
||||
export function flatten<T, D extends number = 1>(arr: readonly T[], depth = 1 as D): Array<FlatArray<T[], D>> {
|
||||
const result: Array<FlatArray<T[], D>> = [];
|
||||
const flooredDepth = Math.floor(depth);
|
||||
|
||||
const recursive = (arr: readonly T[], currentDepth: number) => {
|
||||
for (const item of arr) {
|
||||
if (Array.isArray(item) && currentDepth < flooredDepth) {
|
||||
recursive(item, currentDepth + 1);
|
||||
} else {
|
||||
result.push(item as FlatArray<T[], D>);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
recursive(arr, 0);
|
||||
return result;
|
||||
}
|
@ -9,6 +9,7 @@ export { dropRight } from './dropRight.ts';
|
||||
export { dropRightWhile } from './dropRightWhile.ts';
|
||||
export { dropWhile } from './dropWhile.ts';
|
||||
export { fill } from './fill.ts';
|
||||
export { flatten } from './flatten.ts';
|
||||
export { forEachRight } from './forEachRight.ts';
|
||||
export { groupBy } from './groupBy.ts';
|
||||
export { intersection } from './intersection.ts';
|
||||
|
Loading…
Reference in New Issue
Block a user