feat(sampleSize): Add sampleSize (#101)

This commit is contained in:
jgjgill 2024-06-30 19:36:26 +09:00 committed by GitHub
parent 6c9c0d1c26
commit 02f14b3697
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 153 additions and 0 deletions

View File

@ -0,0 +1,15 @@
import { bench, describe } from 'vitest';
import { sampleSize as sampleSizeToolkit } from 'es-toolkit';
import { sampleSize as sampleSizeLodash } from 'lodash';
describe('sampleSize', () => {
bench('es-toolkit/sampleSize', () => {
const array = [1, 2, 3, 4, 5];
sampleSizeToolkit(array, 3);
});
bench('lodash/sampleSize', () => {
const array = [1, 2, 3, 4, 5];
sampleSizeLodash(array, 3);
});
});

View File

@ -65,6 +65,7 @@ function sidebar(): DefaultTheme.Sidebar {
{ text: 'maxBy', link: '/reference/array/maxBy' },
{ text: 'partition', link: '/reference/array/partition' },
{ text: 'sample', link: '/reference/array/sample' },
{ text: 'sampleSize', link: '/reference/array/sampleSize' },
{ text: 'shuffle', link: '/reference/array/shuffle' },
{ text: 'take', link: '/reference/array/take' },
{ text: 'takeWhile', link: '/reference/array/takeWhile' },

View File

@ -64,6 +64,7 @@ function sidebar(): DefaultTheme.Sidebar {
{ text: 'maxBy', link: '/ko/reference/array/maxBy' },
{ text: 'partition', link: '/ko/reference/array/partition' },
{ text: 'sample', link: '/ko/reference/array/sample' },
{ text: 'sampleSize', link: '/ko/reference/array/sampleSize' },
{ text: 'shuffle', link: '/ko/reference/array/shuffle' },
{ text: 'take', link: '/ko/reference/array/take' },
{ text: 'takeWhile', link: '/ko/reference/array/takeWhile' },

View File

@ -0,0 +1,32 @@
# sampleSize
지정된 `size`의 샘플 요소 배열을 반환해요.
이 함수는 배열과 숫자를 받아요. [Floyd의 알고리즘](https://www.nowherenearithaca.com/2013/05/robert-floyds-tiny-and-beautiful.html)을 사용해서 샘플된 요소들이 포함된 배열을 반환해요.
## 인터페이스
```typescript
export function sampleSize<T>(array: readonly T[], size: number): T[];
```
### 파리미터
- `array` (`T[]`): 샘플링할 배열이에요.
- `size` (`number`): 샘플링할 크기에요.
### 반환 값
(`T[]`): 샘플 크기가 적용된 새로운 배열이에요.
### 에러
`size``array`의 길이보다 크면 에러를 던져요.
## 예시
```typescript
const result = sampleSize([1, 2, 3], 2);
// 결과는 배열의 요소 중 두 개를 포함하는 배열이 돼요.
// [1, 2] or [1, 3] or [2, 3]
```

View File

@ -0,0 +1,32 @@
# sampleSize
Returns a sample element array of a specified `size`.
This function takes an array and a number, and returns an array containing the sampled elements using [Floyd's algorithm](https://www.nowherenearithaca.com/2013/05/robert-floyds-tiny-and-beautiful.html).
## Signature
```typescript
export function sampleSize<T>(array: readonly T[], size: number): T[];
```
### Parameters
- `array` (`T[]`): The array to sample from.
- `size` (`number`): The size of sample.
### Returns
(`T[]`): A new array with sample size applied.
### Throws
Throws an error if `size` is greater than the length of `array`.
## Examples
```typescript
const result = sampleSize([1, 2, 3], 2);
// result will be an array containing two of the elements from the array.
// [1, 2] or [1, 3] or [2, 3]
```

View File

@ -16,6 +16,7 @@ export { maxBy } from './maxBy.ts';
export { minBy } from './minBy.ts';
export { partition } from './partition.ts';
export { sample } from './sample.ts';
export { sampleSize } from './sampleSize.ts';
export { shuffle } from './shuffle.ts';
export { take } from './take.ts';
export { takeRight } from './takeRight.ts';

View File

@ -0,0 +1,30 @@
import { describe, expect, it } from 'vitest';
import { sampleSize } from './sampleSize';
describe('sampleSize', () => {
it('returns a sample element array of a specified size', () => {
const array = [1, 2, 3];
const result = sampleSize(array, 2);
expect(array).toEqual(expect.arrayContaining(result));
});
it('returns an empty array for size 0', () => {
const result = sampleSize([1, 2, 3], 0);
expect(result).toEqual([]);
});
it('returns the same array if the size is equal to the array length', () => {
const array = [1, 2, 3];
const result = sampleSize(array, array.length);
expect(result).toEqual(array);
expect(result).not.toBe(array);
});
it('throws an error if the size is greater than the array length', () => {
expect(() => sampleSize([1, 2, 3], 4)).toThrowErrorMatchingInlineSnapshot(
`[Error: Size must be less than or equal to the length of array.]`
);
});
});

41
src/array/sampleSize.ts Normal file
View File

@ -0,0 +1,41 @@
import { randomInt } from '../math';
/**
* Returns a sample element array of a specified `size`.
*
* This function takes an array and a number, and returns an array containing the sampled elements using Floyd's algorithm.
*
* {@link https://www.nowherenearithaca.com/2013/05/robert-floyds-tiny-and-beautiful.html Floyd's algoritm}
*
* @param {T[]} array - The array to sample from.
* @param {number} size - The size of sample.
* @returns {T[]} A new array with sample size applied.
* @throws {Error} Throws an error if `size` is greater than the length of `array`.
*
* @example
* const result = sampleSize([1, 2, 3], 2)
* // result will be an array containing two of the elements from the array.
* // [1, 2] or [1, 3] or [2, 3]
*/
export function sampleSize<T>(array: readonly T[], size: number): T[] {
if (size > array.length) {
throw new Error('Size must be less than or equal to the length of array.');
}
const result = new Array(size);
const selected = new Set();
for (let step = array.length - size, resultIndex = 0; step < array.length; step++, resultIndex++) {
let index = randomInt(0, step + 1);
if (selected.has(index)) {
index = step;
}
selected.add(index);
result[resultIndex] = array[index];
}
return result;
}