mirror of
https://github.com/toss/es-toolkit.git
synced 2024-11-28 03:34:26 +03:00
feat(keyBy): Add keyBy (#93)
* feat(keyBy): Add keyBy * docs(keyBy): Translate title into Korean * Update docs/ko/reference/array/keyBy.md --------- Co-authored-by: Sojin Park <raon0211@gmail.com>
This commit is contained in:
parent
537745077f
commit
184ce1778d
29
benchmarks/keyBy.bench.ts
Normal file
29
benchmarks/keyBy.bench.ts
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import { bench, describe } from 'vitest';
|
||||||
|
import { keyBy as keyByToolkit } from 'es-toolkit';
|
||||||
|
import { keyBy as keyByLodash } from 'lodash';
|
||||||
|
|
||||||
|
describe('keyBy', () => {
|
||||||
|
bench('es-toolkit/keyBy', () => {
|
||||||
|
const people = [
|
||||||
|
{ name: 'mike', age: 20 },
|
||||||
|
{ name: 'jake', age: 30 },
|
||||||
|
{ name: 'john', age: 25 },
|
||||||
|
{ name: 'sarah', age: 25 },
|
||||||
|
{ name: 'emma', age: 25 },
|
||||||
|
];
|
||||||
|
|
||||||
|
keyByToolkit(people, person => person.name);
|
||||||
|
});
|
||||||
|
|
||||||
|
bench('lodash/keyBy', () => {
|
||||||
|
const people = [
|
||||||
|
{ name: 'mike', age: 20 },
|
||||||
|
{ name: 'jake', age: 30 },
|
||||||
|
{ name: 'john', age: 25 },
|
||||||
|
{ name: 'sarah', age: 25 },
|
||||||
|
{ name: 'emma', age: 25 },
|
||||||
|
];
|
||||||
|
|
||||||
|
keyByLodash(people, person => person.name);
|
||||||
|
});
|
||||||
|
});
|
@ -60,6 +60,7 @@ function sidebar(): DefaultTheme.Sidebar {
|
|||||||
{ text: 'intersection', link: '/reference/array/intersection' },
|
{ text: 'intersection', link: '/reference/array/intersection' },
|
||||||
{ text: 'intersectionBy', link: '/reference/array/intersectionBy' },
|
{ text: 'intersectionBy', link: '/reference/array/intersectionBy' },
|
||||||
{ text: 'intersectionWith', link: '/reference/array/intersectionWith' },
|
{ text: 'intersectionWith', link: '/reference/array/intersectionWith' },
|
||||||
|
{ text: 'keyBy', link: '/reference/array/keyBy' },
|
||||||
{ text: 'minBy', link: '/reference/array/minBy' },
|
{ text: 'minBy', link: '/reference/array/minBy' },
|
||||||
{ text: 'maxBy', link: '/reference/array/maxBy' },
|
{ text: 'maxBy', link: '/reference/array/maxBy' },
|
||||||
{ text: 'partition', link: '/reference/array/partition' },
|
{ text: 'partition', link: '/reference/array/partition' },
|
||||||
|
@ -59,6 +59,7 @@ function sidebar(): DefaultTheme.Sidebar {
|
|||||||
{ text: 'intersection', link: '/ko/reference/array/intersection' },
|
{ text: 'intersection', link: '/ko/reference/array/intersection' },
|
||||||
{ text: 'intersectionBy', link: '/ko/reference/array/intersectionBy' },
|
{ text: 'intersectionBy', link: '/ko/reference/array/intersectionBy' },
|
||||||
{ text: 'intersectionWith', link: '/ko/reference/array/intersectionWith' },
|
{ text: 'intersectionWith', link: '/ko/reference/array/intersectionWith' },
|
||||||
|
{ text: 'keyBy', link: '/ko/reference/array/keyBy' },
|
||||||
{ text: 'minBy', link: '/ko/reference/array/minBy' },
|
{ text: 'minBy', link: '/ko/reference/array/minBy' },
|
||||||
{ text: 'maxBy', link: '/ko/reference/array/maxBy' },
|
{ text: 'maxBy', link: '/ko/reference/array/maxBy' },
|
||||||
{ text: 'partition', link: '/ko/reference/array/partition' },
|
{ text: 'partition', link: '/ko/reference/array/partition' },
|
||||||
|
38
docs/ko/reference/array/keyBy.md
Normal file
38
docs/ko/reference/array/keyBy.md
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
# keyBy
|
||||||
|
|
||||||
|
배열의 요소를 쉽게 찾을 수 있도록, 키-값 쌍을 이루는 객체로 바꿔요.
|
||||||
|
|
||||||
|
이 함수는 파라미터로 배열과 각 요소에서 키를 생성하는 함수를 받아요.
|
||||||
|
키는 함수에서 생성된 키이고, 값은 해당 키를 생성한 요소인 객체를 반환해요.
|
||||||
|
만약 동일한 키를 생성하는 요소가 여러 개 있다면, 그 중 마지막 요소가 값으로 사용돼요.
|
||||||
|
|
||||||
|
## 인터페이스
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
function keyBy<T, K extends string>(arr: readonly T[], getKeyFromItem: (item: T) => K): Record<K, T>;
|
||||||
|
```
|
||||||
|
|
||||||
|
### 파라미터
|
||||||
|
|
||||||
|
- `arr` (`T[]`): 매핑할 배열.
|
||||||
|
- `getKeyFromItem` (`(item: T) => K`): 요소에서 키를 생성하는 함수.
|
||||||
|
|
||||||
|
### 반환 값
|
||||||
|
|
||||||
|
(`Record<K, T>`) 키와 해당 배열 요소들이 매핑된 객체를 반환해요.
|
||||||
|
|
||||||
|
## 예시
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const array = [
|
||||||
|
{ category: 'fruit', name: 'apple' },
|
||||||
|
{ category: 'fruit', name: 'banana' },
|
||||||
|
{ category: 'vegetable', name: 'carrot' },
|
||||||
|
];
|
||||||
|
const result = keyBy(array, item => item.category);
|
||||||
|
// 결과값:
|
||||||
|
// {
|
||||||
|
// fruit: { category: 'fruit', name: 'banana' },
|
||||||
|
// vegetable: { category: 'vegetable', name: 'carrot' }
|
||||||
|
// }
|
||||||
|
```
|
38
docs/reference/array/keyBy.md
Normal file
38
docs/reference/array/keyBy.md
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
# keyBy
|
||||||
|
|
||||||
|
Maps each element of an array based on a provided key-generating function.
|
||||||
|
|
||||||
|
This function takes an array and a function that generates a key from each element. It returns
|
||||||
|
an object where the keys are the generated keys and the values are the corresponding elements.
|
||||||
|
If there are multiple elements generating the same key, the last element among them is used as the value.
|
||||||
|
|
||||||
|
## Signature
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
function keyBy<T, K extends string>(arr: readonly T[], getKeyFromItem: (item: T) => K): Record<K, T>;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Parameters
|
||||||
|
|
||||||
|
- `arr` (`T[]`): The array of elements to be mapped.
|
||||||
|
- `getKeyFromItem` (`(item: T) => K`): A function that generates a key from an element.
|
||||||
|
|
||||||
|
### Returns
|
||||||
|
|
||||||
|
(`Record<K, T>`) An object where keys are mapped to each element of an array.
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const array = [
|
||||||
|
{ category: 'fruit', name: 'apple' },
|
||||||
|
{ category: 'fruit', name: 'banana' },
|
||||||
|
{ category: 'vegetable', name: 'carrot' },
|
||||||
|
];
|
||||||
|
const result = keyBy(array, item => item.category);
|
||||||
|
// result will be:
|
||||||
|
// {
|
||||||
|
// fruit: { category: 'fruit', name: 'banana' },
|
||||||
|
// vegetable: { category: 'vegetable', name: 'carrot' }
|
||||||
|
// }
|
||||||
|
```
|
@ -11,6 +11,7 @@ export { groupBy } from './groupBy';
|
|||||||
export { intersection } from './intersection';
|
export { intersection } from './intersection';
|
||||||
export { intersectionBy } from './intersectionBy';
|
export { intersectionBy } from './intersectionBy';
|
||||||
export { intersectionWith } from './intersectionWith';
|
export { intersectionWith } from './intersectionWith';
|
||||||
|
export { keyBy } from './keyBy';
|
||||||
export { maxBy } from './maxBy';
|
export { maxBy } from './maxBy';
|
||||||
export { minBy } from './minBy';
|
export { minBy } from './minBy';
|
||||||
export { partition } from './partition';
|
export { partition } from './partition';
|
||||||
|
36
src/array/keyBy.spec.ts
Normal file
36
src/array/keyBy.spec.ts
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
import { describe, expect, it } from 'vitest';
|
||||||
|
import { keyBy } from './keyBy';
|
||||||
|
|
||||||
|
describe('keyBy', () => {
|
||||||
|
it('should return the mapped object by given key', () => {
|
||||||
|
const people = [
|
||||||
|
{ name: 'mike', age: 20 },
|
||||||
|
{ name: 'jake', age: 30 },
|
||||||
|
];
|
||||||
|
|
||||||
|
const result = keyBy(people, person => person.age.toString());
|
||||||
|
expect(result).toEqual({ 20: { name: 'mike', age: 20 }, 30: { name: 'jake', age: 30 } });
|
||||||
|
|
||||||
|
const result2 = keyBy(people, person => person.name);
|
||||||
|
expect(result2).toEqual({ mike: { name: 'mike', age: 20 }, jake: { name: 'jake', age: 30 } });
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should overwrite the value when encountering the same key', () => {
|
||||||
|
const people = [
|
||||||
|
{ name: 'mike', age: 20 },
|
||||||
|
{ name: 'mike', age: 30 },
|
||||||
|
];
|
||||||
|
|
||||||
|
const result = keyBy(people, person => person.name);
|
||||||
|
|
||||||
|
expect(result).toEqual({ mike: { name: 'mike', age: 30 } });
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle empty array', () => {
|
||||||
|
const people: Array<{ name: string; age: number }> = [];
|
||||||
|
|
||||||
|
const result = keyBy(people, person => person.name);
|
||||||
|
|
||||||
|
expect(result).toEqual({});
|
||||||
|
});
|
||||||
|
});
|
35
src/array/keyBy.ts
Normal file
35
src/array/keyBy.ts
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/**
|
||||||
|
* Maps each element of an array based on a provided key-generating function.
|
||||||
|
*
|
||||||
|
* This function takes an array and a function that generates a key from each element. It returns
|
||||||
|
* an object where the keys are the generated keys and the values are the corresponding elements.
|
||||||
|
* If there are multiple elements generating the same key, the last element among them is used
|
||||||
|
* as the value.
|
||||||
|
*
|
||||||
|
* @param {T[]} arr - The array of elements to be mapped.
|
||||||
|
* @param {(item: T) => K} getKeyFromItem - A function that generates a key from an element.
|
||||||
|
* @returns {Record<K, T>} An object where keys are mapped to each element of an array.
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* const array = [
|
||||||
|
* { category: 'fruit', name: 'apple' },
|
||||||
|
* { category: 'fruit', name: 'banana' },
|
||||||
|
* { category: 'vegetable', name: 'carrot' }
|
||||||
|
* ];
|
||||||
|
* const result = keyBy(array, item => item.category);
|
||||||
|
* // result will be:
|
||||||
|
* // {
|
||||||
|
* // fruit: { category: 'fruit', name: 'banana' },
|
||||||
|
* // vegetable: { category: 'vegetable', name: 'carrot' }
|
||||||
|
* // }
|
||||||
|
*/
|
||||||
|
export function keyBy<T, K extends string>(arr: readonly T[], getKeyFromItem: (item: T) => K): Record<K, T> {
|
||||||
|
const result = {} as Record<K, T>;
|
||||||
|
|
||||||
|
for (const item of arr) {
|
||||||
|
const key = getKeyFromItem(item);
|
||||||
|
result[key] = item;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user