feat(maxBy): Add maxBy function that select element that have max value by given condition in array (#64)

* feat(maxBy): Add maxBy function

* feat(maxBy): Add benchamark test

* feat(maxBy): Add unit test of maxBy

* docs(maxBy): Add reference of maxBy function

* feat(maxBy): use for-each loop instead of index-increasing fashion

* fix(maxBy): Change code by code review

* fix(maxBy): Changed by code review, all tests are fine

* fix(maxBy): remove explicit undefined return

* fix(maxBy): Fix reference due to signature modification

* Update src/math/maxBy.ts

---------

Co-authored-by: Sojin Park <raon0211@gmail.com>
This commit is contained in:
HyunWoo Lee (Nunu Lee) 2024-06-17 18:39:42 +09:00 committed by GitHub
parent 3ecc06268c
commit 260bae963f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 149 additions and 0 deletions

23
benchmarks/maxBy.bench.ts Executable file
View File

@ -0,0 +1,23 @@
import { bench, describe } from 'vitest';
import { maxBy as maxByToolkit } from 'es-toolkit';
import { maxBy as maxByLodash } from 'lodash';
describe('maxBy', () => {
bench('es-toolkit', () => {
const people = [
{ name: 'Mark', age: 25 },
{ name: 'Nunu', age: 30 },
{ name: 'Overmars', age: 20 },
];
maxByToolkit(people, person => person.age);
});
bench('lodash', () => {
const people = [
{ name: 'Mark', age: 25 },
{ name: 'Nunu', age: 30 },
{ name: 'Overmars', age: 20 },
];
maxByLodash(people, person => person.age);
});
});

View File

@ -0,0 +1,27 @@
# maxBy
주어진 배열 내의 요소들 중에서 조건에 따라 최대값을 가지는 첫 번째 요소를 선택하는 함수에요.
배열이 비어있지 않다면 조건에 따라 최대값을 가지는 첫 번째 요소를 반환하고, 비어있다면 `undefined`를 반환해요.
## 인터페이스
```typescript
function maxBy<T>(elements: T[], selector: (element: T) => number): T
```
### 파라미터
- `elements`: 검색할 요소들의 배열
- `selector`: 요소를 받아서 객체의 속성을 반환하는 함수
### 반환값
함수의 최대값을 가지는 배열의 첫 번째 요소. 만약 배열이 비어있다면 `undefined`를 반환해요.
### 예시
```typescript
maxBy([{ a: 1 }, { a: 2 }, { a: 3 }], x => x.a) // 결과: { a: 3 }
maxBy([], x => x.a) // 결과: undefined
```

View File

@ -0,0 +1,27 @@
# maxBy
Selects the first element of a list that has the maximum value of a function.
If the list is empty, returns `undefined`.
## Signature
```typescript
function maxBy<T>(elements: T[], selector: (element: T) => number): T
```
### Parameters
- `elements`: an array of elements to search through.
- `selector`: a function that takes an element and returns a number that the property of the object.
### Returns
The first element of the list that has the maximum value of the function. If the list is empty, returns `undefined`.
### Example
```typescript
maxBy([{ a: 1 }, { a: 2 }, { a: 3 }], x => x.a) // Returns: { a: 3 }
maxBy([], x => x.a) // Returns: undefined
```

View File

@ -3,3 +3,4 @@ export { random } from './random';
export { randomInt } from './randomInt';
export { round } from './round';
export { sum } from './sum';
export { maxBy } from './maxBy';

39
src/math/maxBy.spec.ts Normal file
View File

@ -0,0 +1,39 @@
import { describe, expect, it } from "vitest";
import { maxBy } from './maxBy';
describe('maxBy', () => {
it('maxBy selects one max value in array', () => {
const people = [
{ name: 'Mark', age: 25 },
{ name: 'Nunu', age: 30 },
{ name: 'Overmars', age: 20 },
];
const result = maxBy(people, person => person.age);
expect(result).toEqual({ name: 'Nunu', age: 30 });
});
it('if there are two max values, first one is selected', () => {
const people = [
{ name: 'Mark', age: 25 },
{ name: 'Nunu', age: 30 },
{ name: 'Overmars', age: 30 },
];
const result = maxBy(people, person => person.age);
expect(result).toEqual({ name: 'Nunu', age: 30 });
});
it('if array is single-element, return unique element of array', () => {
const people = [
{ name: 'Mark', age: 25 },
];
const result = maxBy(people, person => person.age);
expect(result).toEqual({ name: 'Mark', age: 25 });
});
it('if array is empty, return undefined', () => {
type Person = { name: string, age: number };
const people: Person[] = [];
const result = maxBy(people, person => person.age);
expect(result).toBeUndefined();
});
});

32
src/math/maxBy.ts Normal file
View File

@ -0,0 +1,32 @@
/**
* Returns the element of the specified array that has the maximum value, according to the specified selector.
*
* This function takes an array of elements and a selector function, and returns the element with the maximum value according to the selector.
*
* @param {T[]} elements - An array of elements to be compared.
* @param {(element: T) => number} selector - A function that takes an element and returns a number.
* @returns {T} The element with the maximum value according to the selector.
*
* @example
* const people = [
* { name: 'Mark', age: 25 },
* { name: 'Nunu', age: 30 },
* { name: 'Overmars', age: 20 }
* ];
* const result = maxBy(people, person => person.age);
* // result will be { name: 'Nunu', age: 30 }
*/
export function maxBy<T>(elements: T[], selector: (element: T) => number): T {
let maxElement = elements[0];
let max = -Infinity;
for (const element of elements) {
const value = selector(element);
if (value > max) {
max = value;
maxElement = element;
}
}
return maxElement;
}