diff --git a/benchmarks/without.bench.ts b/benchmarks/without.bench.ts new file mode 100644 index 000000000..f8cbd26f0 --- /dev/null +++ b/benchmarks/without.bench.ts @@ -0,0 +1,31 @@ +import { bench, describe } from 'vitest'; +import { without as withoutEsToolkit } from 'es-toolkit'; +import { without as withoutLodash } from 'lodash'; + +const generateArray = (length: number, max: number) => Array.from({ length }, () => Math.floor(Math.random() * max)); + +describe('without, small arrays', () => { + const array = [1, 2, 3, 4, 5]; + const values = [2, 4]; + + bench('es-toolkit/without', () => { + withoutEsToolkit(array, ...values); + }); + + bench('lodash/without', () => { + withoutLodash(array, ...values); + }); +}); + +describe('without, large arrays', () => { + const array = generateArray(10000, 1000); + const values = generateArray(100, 1000); + + bench('es-toolkit/without', () => { + withoutEsToolkit(array, ...values); + }); + + bench('lodash/without', () => { + withoutLodash(array, ...values); + }); +}); diff --git a/docs/ko/reference/array/without.md b/docs/ko/reference/array/without.md new file mode 100644 index 000000000..9916b5bc1 --- /dev/null +++ b/docs/ko/reference/array/without.md @@ -0,0 +1,42 @@ +# without + +배열에서 주어진 값을 제거한 새로운 배열을 만들어요. + +값이 같은지는 [SameValueZero](https://tc39.es/ecma262/multipage/abstract-operations.html#sec-samevaluezero) 기준으로 비교하기 때문에, `NaN`과도 사용할 수 있어요. + +## 인터페이스 + +```typescript +function without(array: T[], ...values: T[]): T[]; +``` + +### 파라미터 + +- `array` (`T[]`): 값을 제거할 배열. +- `values` (`...T[]`): 제거할 값. + +### 반환 값 + +(`T[]`) 주어진 값을 제외한 새 배열. + +## Examples + +```typescript +import { without } from 'es-toolkit/array'; + +// 배열에서 지정된 값을 제거합니다 +without([1, 2, 3, 4, 5], 2, 4); +// 결과 값: [1, 3, 5] + +// 배열에서 지정된 문자열 값을 제거합니다 +without(['a', 'b', 'c', 'a'], 'a'); +// 결과 값: ['b', 'c'] + +// 지정된 값이 배열에 없는 경우를 처리합니다 +without([1, 2, 3], 4, 5); +// 결과 값: [1, 2, 3] + +// 다른 유형의 값을 포함한 경우를 처리합니다 +without([1, '2', 3, '4'], 2, '4'); +// 결과 값: [1, '2', 3] +``` diff --git a/docs/reference/array/without.md b/docs/reference/array/without.md new file mode 100644 index 000000000..51a920624 --- /dev/null +++ b/docs/reference/array/without.md @@ -0,0 +1,42 @@ +# without + +Creates an array that excludes all specified values. + +It correctly excludes `NaN`, as it compares values using [SameValueZero](https://tc39.es/ecma262/multipage/abstract-operations.html#sec-samevaluezero). + +## Signature + +```typescript +function without(array: T[], ...values: T[]): T[]; +``` + +### Parameters + +- `array` (`T[]`): The array to exclude values. +- `values` (`...T[]`): The values to exclude. + +### Returns + +(`T[]`) A new array without the specified values. + +## Examples + +```typescript +import { without } from 'es-toolkit/array'; + +// Removes the specified values from the array +without([1, 2, 3, 4, 5], 2, 4); +// Returns: [1, 3, 5] + +// Removes specified string values from the array +without(['a', 'b', 'c', 'a'], 'a'); +// Returns: ['b', 'c'] + +// Handles cases where none of the specified values are in the array +without([1, 2, 3], 4, 5); +// Returns: [1, 2, 3] + +// Handles cases with different types of values +without([1, '2', 3, '4'], 2, '4'); +// Returns: [1, '2', 3] +``` diff --git a/src/array/index.ts b/src/array/index.ts index 7469ca9f5..e69de8f20 100644 --- a/src/array/index.ts +++ b/src/array/index.ts @@ -28,6 +28,7 @@ export { unionWith } from './unionWith.ts'; export { uniq } from './uniq.ts'; export { uniqBy } from './uniqBy.ts'; export { uniqWith } from './uniqWith.ts'; +export { without } from './without.ts'; export { xor } from './xor.ts'; export { xorBy } from './xorBy.ts'; export { xorWith } from './xorWith.ts'; diff --git a/src/array/without.spec.ts b/src/array/without.spec.ts new file mode 100644 index 000000000..d5da295c4 --- /dev/null +++ b/src/array/without.spec.ts @@ -0,0 +1,35 @@ +import { describe, expect, it } from 'vitest'; +import { without } from './without'; + +describe('without', () => { + it('should return an empty array when the input array is empty', () => { + expect(without([], 1, 2, 3)).toEqual([]); + }); + + it('should return the same array when no values are provided to exclude', () => { + expect(without([1, 2, 3])).toEqual([1, 2, 3]); + }); + + it('should return a new array excluding the specified values', () => { + expect(without([1, 2, 3, 4, 5], 2, 4)).toEqual([1, 3, 5]); + expect(without(['a', 'b', 'c', 'a'], 'a')).toEqual(['b', 'c']); + }); + + it('should handle cases where none of the specified values are in the array', () => { + expect(without([1, 2, 3], 4, 5)).toEqual([1, 2, 3]); + }); + + it('should handle cases with different types of values', () => { + expect(without([1, '2', 3, '4'], 2, '4')).toEqual([1, '2', 3]); + expect(without([1, '1', 2, '2'], 1, '2')).toEqual(['1', 2]); + }); + + it('should handle NaN values correctly', () => { + expect(without([NaN, 1, 2, NaN, 3], NaN)).toEqual([1, 2, 3]); + }); + + it('should treat +0 and -0 as equal', () => { + expect(without([0, -0, 1, 2], 0)).toEqual([1, 2]); + expect(without([0, -0, 1, 2], -0)).toEqual([1, 2]); + }); +}); diff --git a/src/array/without.ts b/src/array/without.ts new file mode 100644 index 000000000..3b39238dc --- /dev/null +++ b/src/array/without.ts @@ -0,0 +1,24 @@ +/** + * Creates an array that excludes all specified values. + * + * It correctly excludes `NaN`, as it compares values using [SameValueZero](https://tc39.es/ecma262/multipage/abstract-operations.html#sec-samevaluezero). + * + * @template T The type of elements in the array. + * @param {T[]} array - The array to filter. + * @param {...T[]} values - The values to exclude. + * @returns {T[]} A new array without the specified values. + * + * @example + * // Removes the specified values from the array + * without([1, 2, 3, 4, 5], 2, 4); + * // Returns: [1, 3, 5] + * + * @example + * // Removes specified string values from the array + * without(['a', 'b', 'c', 'a'], 'a'); + * // Returns: ['b', 'c'] + */ +export function without(array: readonly T[], ...values: T[]): T[] { + const valuesSet = new Set(values); + return array.filter(item => !valuesSet.has(item)); +}