Skip to content

Commit

Permalink
feat(remove): Implement remove
Browse files Browse the repository at this point in the history
  • Loading branch information
raon0211 committed Dec 27, 2024
1 parent 610aeae commit b6c4368
Show file tree
Hide file tree
Showing 10 changed files with 375 additions and 0 deletions.
29 changes: 29 additions & 0 deletions docs/ja/reference/array/remove.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# remove

与えられた条件関数に従って配列から要素を削除します。

この関数は `arr` を直接変更します。
元の配列を変更せずに要素を削除するには、[Array.prototype.filter](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/filter) を使用してください。

## インターフェース

```typescript
function remove<T>(arr: T[], shouldRemoveElement: (value: T, index: number, array: T[]) => boolean): T[];
```

### パラメータ

- `arr` (`T[]`): 変更する配列です。
- `shouldRemoveElement` (`(value: T, index: number, array: T[]) => boolean`): 要素を削除するかどうかを決定するために、各反復で呼び出される関数です。

### 戻り値

(`T[]`): 指定された要素が削除された修正済み配列です。

##

```typescript
const numbers = [1, 2, 3, 4, 5];
remove(numbers, value => value % 2 === 0);
console.log(numbers); // [1, 3, 5]
```
29 changes: 29 additions & 0 deletions docs/ko/reference/array/remove.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# remove

주어진 조건 함수에 따라 배열에서 요소를 제거해요.

이 함수는 `arr`을 직접 변경해요.
원본 배열을 수정하지 않고 요소를 제거하려면 [Array.prototype.filter](https://developer.mozilla.org/ko-KR/docs/Web/JavaScript/Reference/Global_Objects/Array/filter)를 사용하세요.

## 인터페이스

```typescript
function remove<T>(arr: T[], shouldRemoveElement: (value: T, index: number, array: T[]) => boolean): T[];
```

### 파라미터

- `arr` (`T[]`): 수정할 배열.
- `shouldRemoveElement` (`(value: T, index: number, array: T[]) => boolean`): 요소를 제거할지 결정하기 위해 각 반복마다 호출되는 함수.

### 반환 값

(`T[]`): 지정된 요소가 제거된 수정된 배열.

## 예시

```typescript
const numbers = [1, 2, 3, 4, 5];
remove(numbers, value => value % 2 === 0);
console.log(numbers); // [1, 3, 5]
```
29 changes: 29 additions & 0 deletions docs/reference/array/remove.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# remove

Removes elements from an array based on a predicate function.

This function changes `arr` in place.
If you want to remove elements without modifying the original array, use [Array.prototype.filter](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter).

## Signature

```typescript
function remove<T>(arr: T[], shouldRemoveElement: (value: T, index: number, array: T[]) => boolean): T[];
```

### Parameters

- `arr` (`T[]`): The array to modify.
- `shouldRemoveElement` (`(value: T, index: number, array: T[]) => boolean`): The function invoked per iteration to determine if an element should be removed.

### Returns

(`T[]`): The modified array with the specified elements removed.

## Examples

```typescript
const numbers = [1, 2, 3, 4, 5];
remove(numbers, value => value % 2 === 0);
console.log(numbers); // [1, 3, 5]
```
29 changes: 29 additions & 0 deletions docs/zh_hans/reference/array/remove.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# remove

根据谓词函数从数组中移除元素。

此函数会直接修改 `arr`
如果希望在不修改原始数组的情况下移除元素,请使用 `filter`

## 签名

```typescript
function remove<T>(arr: T[], shouldRemoveElement: (value: T, index: number, array: T[]) => boolean): T[];
```

### 参数

- `arr` (`T[]`): 要修改的数组。
- `shouldRemoveElement` (`(value: T, index: number, array: T[]) => boolean`): 每次迭代时调用的函数,用于确定是否应移除某个元素。

### 返回值

(`T[]`): 移除指定元素后的修改数组。

## 示例

```typescript
const numbers = [1, 2, 3, 4, 5];
remove(numbers, (value) => value % 2 === 0);
console.log(numbers); // [1, 3, 5]
```
1 change: 1 addition & 0 deletions src/array/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export { orderBy } from './orderBy.ts';
export { partition } from './partition.ts';
export { pull } from './pull.ts';
export { pullAt } from './pullAt.ts';
export { remove } from './remove.ts';
export { sample } from './sample.ts';
export { sampleSize } from './sampleSize.ts';
export { shuffle } from './shuffle.ts';
Expand Down
34 changes: 34 additions & 0 deletions src/array/remove.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { describe, expect, it } from 'vitest';
import { remove } from './remove';

describe('remove', () => {
it('should remove elements based on the predicate function', () => {
const numbers = [1, 2, 3, 4, 5];
const result = remove(numbers, value => value % 2 === 0);
expect(result).toEqual([1, 3, 5]);
});

it('should handle sparse arrays correctly', () => {
const sparseArray = [1, , 3, , 5];
const result = remove(sparseArray, value => value === undefined);
expect(result).toEqual([1, 3, 5]);
});

it('should return an empty array if all elements are removed', () => {
const numbers = [1, 2, 3, 4, 5];
const result = remove(numbers, () => true);
expect(result).toEqual([]);
});

it('should not remove any elements if the predicate always returns false', () => {
const numbers = [1, 2, 3, 4, 5];
const result = remove(numbers, () => false);
expect(result).toEqual([1, 2, 3, 4, 5]);
});

it('should work with an empty array', () => {
const emptyArray: number[] = [];
const result = remove(emptyArray, () => true);
expect(result).toEqual([]);
});
});
41 changes: 41 additions & 0 deletions src/array/remove.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/**
* Removes elements from an array based on a predicate function.
*
* This function changes `arr` in place.
* If you want to remove elements without modifying the original array, use `filter`.
*
* @template T
* @param {T[]} arr - The array to modify.
* @param {(value: T, index: number, array: T[]) => boolean} shouldRemoveElement - The function invoked per iteration to determine if an element should be removed.
* @returns {T[]} The modified array with the specified elements removed.
*
* @example
* const numbers = [1, 2, 3, 4, 5];
* remove(numbers, (value) => value % 2 === 0);
* console.log(numbers); // [1, 3, 5]
*/
export function remove<T>(arr: T[], shouldRemoveElement: (value: T, index: number, array: T[]) => boolean): T[] {
const originalArr = arr.slice();
const removed = [];

let resultIndex = 0;

for (let i = 0; i < arr.length; i++) {
if (shouldRemoveElement(arr[i], i, originalArr)) {
removed.push(arr[i]);
continue;
}

// For handling sparse arrays
if (!Object.hasOwn(arr, i)) {
delete arr[resultIndex++];
continue;
}

arr[resultIndex++] = arr[i];
}

arr.length = resultIndex;

return removed;
}
87 changes: 87 additions & 0 deletions src/compat/array/remove.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import { describe, expect, it } from 'vitest';
import { remove } from './remove';

const isEven = function (n: number) {
return n % 2 == 0;
};

describe('remove', () => {
it('should modify the array and return removed elements', () => {
const array = [1, 2, 3, 4];
const actual = remove(array, isEven);

expect(array).toEqual([1, 3]);
expect(actual).toEqual([2, 4]);
});

it('should provide correct `predicate` arguments', () => {
const argsList: any[] = [];
const array = [1, 2, 3];
const clone = array.slice();

remove(array, function (n, index) {
const args = Array.prototype.slice.call(arguments);
args[2] = args[2].slice();
argsList.push(args);
return isEven(index);
});

expect(argsList).toEqual([
[1, 0, clone],
[2, 1, clone],
[3, 2, clone],
]);
});

it('should work with `_.matches` shorthands', () => {
const objects = [
{ a: 0, b: 1 },
{ a: 1, b: 2 },
];
remove(objects, { a: 1 });
expect(objects).toEqual([{ a: 0, b: 1 }]);
});

it('should work with `_.matchesProperty` shorthands', () => {
const objects = [
{ a: 0, b: 1 },
{ a: 1, b: 2 },
];
remove(objects, ['a', 1]);
expect(objects).toEqual([{ a: 0, b: 1 }]);
});

it('should work with `_.property` shorthands', () => {
const objects = [{ a: 0 }, { a: 1 }];
remove(objects, 'a');
expect(objects).toEqual([{ a: 0 }]);
});

it('should preserve holes in arrays', () => {
const array = [1, 2, 3, 4];
delete array[1];
delete array[3];

remove(array, n => n === 1);

expect('0' in array).toBe(false);
expect('2' in array).toBe(false);
});

it('should treat holes as `undefined`', () => {
const array = [1, 2, 3];
delete array[1];

remove(array, n => n == null);

expect(array).toEqual([1, 3]);
});

it('should not mutate the array until all elements to remove are determined', () => {
const array = [1, 2, 3];

remove(array, (n, index) => isEven(index));

expect(array).toEqual([2]);
});
});
95 changes: 95 additions & 0 deletions src/compat/array/remove.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import { remove as removeToolkit } from '../../array/remove.ts';
import { iteratee } from '../util/iteratee.ts';

/**
* Removes elements from an array based on a predicate function.
*
* @param {ArrayLike<T>} arr - The array to iterate over.
* @param {(value: T, index: number, arr: ArrayLike<T>) => boolean} shouldRemoveElement - The function invoked per iteration.
* @returns {T[]} - Returns the modified array with the specified elements removed.
*
* @example
* const array = [1, 2, 3];
* remove(array, value => value % 2 === 0); // => [1, 3]
*/
export function remove<T>(
arr: ArrayLike<T>,
shouldRemoveElement: (value: T, index: number, arr: ArrayLike<T>) => boolean
): T[];

/**
* Removes elements from an array based on a partial object match.
*
* @param {ArrayLike<T>} arr - The array to iterate over.
* @param {Partial<T>} shouldRemoveElement - The partial object to match against each element.
* @returns {T[]} - Returns the modified array with the specified elements removed.
*
* @example
* const objects = [{ a: 1 }, { a: 2 }, { a: 3 }];
* remove(objects, { a: 1 }); // => [{ a: 2 }, { a: 3 }]
*/
export function remove<T>(arr: ArrayLike<T>, shouldRemoveElement: Partial<T>): T[];

/**
* Removes elements from an array based on a property-value pair match.
*
* @param {ArrayLike<T>} arr - The array to iterate over.
* @param {[keyof T, unknown]} shouldRemoveElement - The property-value pair to match against each element.
* @returns {T[]} - Returns the modified array with the specified elements removed.
*
* @example
* const objects = [{ a: 1 }, { a: 2 }, { a: 3 }];
* remove(objects, ['a', 1]); // => [{ a: 2 }, { a: 3 }]
*/
export function remove<T>(arr: ArrayLike<T>, shouldRemoveElement: [keyof T, unknown]): T[];

/**
* Removes elements from an array based on a property key.
*
* @param {ArrayLike<T>} arr - The array to iterate over.
* @param {keyof T} shouldRemoveElement - The key of the property to match against each element.
* @returns {T[]} - Returns the modified array with the specified elements removed.
*
* @example
* const objects = [{ a: 0 }, { a: 1 }];
* remove(objects, 'a'); // => [{ a: 0 }]
*/
export function remove<T, K extends keyof T>(arr: ArrayLike<T>, shouldRemoveElement: K): T[];

/**
* Removes elements from an array based on various criteria.
*
* @param {ArrayLike<T>} arr - The array to iterate over.
* @param {(value: T, index: number, arr: ArrayLike<T>) => boolean | Partial<T> | [keyof T, unknown] | keyof T} shouldRemoveElement - The function invoked per iteration, a partial object, a property-value pair, or a key to match against each element.
* @returns {T[]} - Returns the modified array with the specified elements removed.
*
* @example
* // Using a predicate function
* const numbers = [1, 2, 3, 4, 5];
* remove(numbers, value => value % 2 === 0); // => [1, 3, 5]
*
* @example
* // Using a partial object
* const objects = [{ a: 1 }, { a: 2 }, { a: 3 }];
* remove(objects, { a: 1 }); // => [{ a: 2 }, { a: 3 }]
*
* @example
* // Using a property-value pair
* const objects = [{ a: 1 }, { a: 2 }, { a: 3 }];
* remove(objects, ['a', 1]); // => [{ a: 2 }, { a: 3 }]
*
* @example
* // Using a property key
* const objects = [{ a: 0 }, { a: 1 }];
* remove(objects, 'a'); // => [{ a: 0 }]
*/
export function remove<T>(
arr: ArrayLike<T>,
shouldRemoveElement:
| ((value: T, index: number, arr: ArrayLike<T>) => boolean)
| Partial<T>
| [keyof T, unknown]
| keyof T
): T[] {
return removeToolkit(arr as T[], iteratee(shouldRemoveElement));
}
1 change: 1 addition & 0 deletions src/compat/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ export { nth } from './array/nth.ts';
export { orderBy } from './array/orderBy.ts';
export { pull } from './array/pull.ts';
export { pullAll } from './array/pullAll.ts';
export { remove } from './array/remove.ts';
export { reverse } from './array/reverse.ts';
export { sample } from './array/sample.ts';
export { size } from './array/size.ts';
Expand Down

0 comments on commit b6c4368

Please sign in to comment.