feat(countBy): Add countBy function (#117)

* [feature/#88] Add countBy.ts

* [feature/#88] Add benchmark test of countBy

* [feature/#88] Add test code

* [feature/#88] Add countBy references

* Update docs/ko/reference/array/countBy.md

* Apply suggestions from code review

---------

Co-authored-by: Sojin Park <raon0211@gmail.com>
This commit is contained in:
HyunWoo Lee (Nunu Lee) 2024-07-03 10:09:12 +09:00 committed by GitHub
parent a82eb933ae
commit 373d63b980
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 133 additions and 0 deletions

View File

@ -0,0 +1,17 @@
import { bench, describe } from 'vitest';
import { countBy as countByToolkit } from 'es-toolkit';
import { countBy as countByLodash } from 'lodash';
describe('countBy', () => {
bench('es-toolkit/countBy', () => {
countByToolkit([1.2, 2.4, 3.6, 2.2, 3.4, 3.6], (item: number) => {
return Math.floor(item).toString();
});
});
bench('lodash/countBy', () => {
countByLodash([1.2, 2.4, 3.6, 2.2, 3.4, 3.6], (item: number) => {
return Math.floor(item).toString();
});
});
});

View File

@ -0,0 +1,30 @@
# countBy
배열에 속해 있는 요소를 `mapper` 함수가 반환하는 값 기준으로 분류하고, 개수를 세요.
## 인터페이스
```typescript
function countBy<T>(arr: T[], mapper: (item: T) => string): Record<string, number>
```
### 파라미터
- `arr` (`T[]`): 요소의 갯수를 세고자 하는 배열
- `mapper` (`(item: T) => string`): 요소를 분류할 기준이 되는 값을 반환하는 함수
### 반환 값
(`Record<string, number>`) 각 요소가 분류별로 몇 개 있는지를 계산한 객체
## 예시
```javascript
import { countBy } from 'es-toolkit/array';
const array = [1, 2, 3, 4, 5, 6];
const result = countBy(array, x => x % 2 === 0 ? 'even' : 'odd');
console.log(result);
// 출력: { 'odd': 3, 'even': 3 }
```

View File

@ -0,0 +1,31 @@
# countBy
Count the occurrences of each item in an array based on a `mapper` function.
## Signature
```typescript
function countBy<T>(arr: T[], mapper: (item: T) => string): Record<string, number>
```
### Parameters
- `arr` (`T[]`): The input array to count occurrences.
- `mapper` (`(item: T) => string`): The transformation function that maps each item to a string key.
### Returns
(`Record<string, number>`) An object containing the count of each item based on the transformation function.
## Examples
```javascript
import { countBy } from 'es-toolkit/array';
const array = [1, 2, 3, 4, 5, 6];
const result = countBy(array, x => x % 2 === 0 ? 'even' : 'odd');
console.log(result);
// Output: { 'odd': 3, 'even': 3 }
```

26
src/array/countBy.spec.ts Normal file
View File

@ -0,0 +1,26 @@
import { describe, expect, it } from 'vitest';
import {countBy} from "./countBy.ts";
describe('countBy', () => {
it('should count the occurrences of each item in an array', () => {
const arr = [1, 2, 3, 4, 5, 1, 2, 3, 4, 5];
const result = countBy(arr, String);
expect(result).toEqual({
'1': 2,
'2': 2,
'3': 2,
'4': 2,
'5': 2,
});
});
it('should count the occurrences of each item in an array that applied transformer', () => {
const arr = [1, 2, 3, 4, 5, 1, 2, 3, 4, 5];
const result = countBy(arr, (item) => item % 2 === 0 ? 'even' : 'odd');
expect(result).toEqual({
'odd': 6,
'even': 4,
});
})
});

28
src/array/countBy.ts Normal file
View File

@ -0,0 +1,28 @@
/**
* Count the occurrences of each item in an array
* based on a transformation function.
*
* This function takes an array and a transformation function
* that converts each item in the array to a string. It then
* counts the occurrences of each transformed item and returns
* an object with the transformed items as keys and the counts
* as values.
*
* @template T - The type of the items in the input array.
*
* @param {T[]} arr - The input array to count occurrences.
* @param {(item: T) => string} mapper - The transformation function that maps each item to a string key.
* @returns {Record<string, number>} An object containing the transformed items as keys and the
* counts as values.
*/
export function countBy<T>(arr: T[], mapper: (item: T) => string): Record<string, number> {
const result: Record<string, number> = {};
for (const item of arr) {
const key = mapper(item);
result[key] = (result[key] ?? 0) + 1;
}
return result;
}

View File

@ -1,5 +1,6 @@
export { chunk } from './chunk.ts';
export { compact } from './compact.ts';
export { countBy } from './countBy.ts';
export { difference } from './difference.ts';
export { differenceBy } from './differenceBy.ts';
export { differenceWith } from './differenceWith.ts';