Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(utils): chunk 유틸 함수 구현 #184

Merged
merged 11 commits into from
May 31, 2024
6 changes: 6 additions & 0 deletions .changeset/loud-zebras-shave.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@modern-kit/types": minor
"@modern-kit/utils": minor
---

feat(utils): chunk 유틸 함수 추가 및 Interger, NaturalNumber WholeNumber 유틸 타입 추가
44 changes: 44 additions & 0 deletions docs/docs/utils/array/chunk.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# chunk

주어진 배열을 지정된 `size`만큼의 작은 배열로 나누어 반환하는 유틸리티 함수입니다.
`size === 0` 이거나 배열이 비어있는 경우 빈 배열을 반환하며, `size <= array.length`인 경우 전체 배열을 하나의 배열로 감싸서 반환합니다.

## Code

[🔗 실제 구현 코드 확인](https://github.com/modern-agile-team/modern-kit/blob/main/packages/utils/src/array/chunk/index.ts)

## Interface

```ts title="typescript"
const chunk = <T, U extends number>(
array: T[],
size: NaturalNumber<U>
): T[][]
```

## Usage

```ts title="typescript"
import { chunk } from '@modern-kit/utils';

const array1 = [1, 2, 3, 4, 5];
const size1 = 2;
chunk(array1, size1); // [[1, 2], [3, 4], [5]]

const array2 = ['a', 'b', 'c', 'd'];
const size2 = 3;
chunk(array2, size2); // [['a', 'b', 'c'], ['d']]

const array3 = [1, 2, 3, 4];
const size3 = 5;
chunk(array3, size3); // [[1, 2, 3, 4]]

const array4 = [];
const size4 = 2;
chunk(array4, size4); // []
```

## Caveats
`size`는 `1` 이상의 자연수여야 합니다. `NaturalNumber<U>` 타입을 사용하여 이를 강제합니다.
`size === 0`이거나 `size === NaN`일 경우 빈 배열을 반환합니다.
`size < array.length`인 경우 전체 배열을 하나의 배열로 감싸서 반환합니다.
3 changes: 3 additions & 0 deletions packages/types/src/Integer/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export type Integer<T extends number> = `${T}` extends `${string}.${string}`
? never
: T;
7 changes: 7 additions & 0 deletions packages/types/src/NaturalNumber/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { Integer } from 'Integer';

export type NaturalNumber<T extends number> = Integer<T> extends never
? never
: `${T}` extends `-${string}` | '0'
? never
: T;
Comment on lines +3 to +7
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Integer, NaturalNumber 모두 멋진 타입이네요!
0을 포함하는 범 자연수 Whole Number도 있으면 좋겠네요 🤗

7 changes: 7 additions & 0 deletions packages/types/src/WholeNumber/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { Integer } from 'Integer';

export type WholeNumber<T extends number> = Integer<T> extends never
? never
: `${T}` extends `-${string}`
? never
: T;
3 changes: 3 additions & 0 deletions packages/types/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,6 @@ export * from './Nullable';
export * from './ObjectEntries';
export * from './ObjectKeys';
export * from './Promiseable';
export * from './Integer';
export * from './NaturalNumber';
export * from './WholeNumber';
44 changes: 44 additions & 0 deletions packages/utils/src/array/chunk/chunk.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { chunk } from '../chunk';

describe('chunk', () => {
it('splits the array according to the second parameter', () => {
const arr1 = [1, 2, 3, 4, 5, 6];
expect(chunk(arr1, 1)).toEqual([[1], [2], [3], [4], [5], [6]]);
expect(chunk(arr1, 2)).toEqual([
[1, 2],
[3, 4],
[5, 6],
]);

const arr2 = [1, 2, 3, 4, 5];
expect(chunk(arr2, 3)).toEqual([
[1, 2, 3],
[4, 5],
]);
});

it('returns an array of each element when the second parameter is 1', () => {
const arr = [1, 2, 3, 4, 5, 6];
expect(chunk(arr, 1)).toEqual([[1], [2], [3], [4], [5], [6]]);
});

it('returns an empty array when given an empty array', () => {
const arr = [] as [];
expect(chunk(arr, 3)).toEqual([]);
});

it('returns the array as is if the chunk size is greater than the length of the array', () => {
const arr = [1, 2];
expect(chunk(arr, 3)).toEqual([arr]);
});

it('returns an empty array if the second parameter is 0', () => {
const arr = [1, 2];
expect(chunk(arr, 0 as number)).toEqual([]);
});

it('returns an empty array if the second parameter is NaN', () => {
const arr = [1, 2];
expect(chunk(arr, NaN)).toEqual([]);
});
});
21 changes: 21 additions & 0 deletions packages/utils/src/array/chunk/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { NaturalNumber } from '@modern-kit/types';

export const chunk = <T, U extends number>(
array: T[],
size: NaturalNumber<U>
): T[][] => {
if (array.length === 0 || Number.isNaN(size) || size === 0) {
return [];
}

if (size >= array.length) {
return [array];
}

return array.reduce((result, _, index) => {
if (index % size === 0) {
result.push(array.slice(index, index + size));
}
return result;
}, [] as T[][]);
};
1 change: 1 addition & 0 deletions packages/utils/src/array/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from './countOccurrencesInArray';
export * from './excludeElements';
export * from './chunk';