mirror of
https://github.com/toss/es-toolkit.git
synced 2024-12-01 02:33:54 +03:00
feat(filter): add filter
function (#610)
* feat: create filter function * test: filter * docs: filter * fix: test case description --------- Co-authored-by: Sojin Park <raon0211@toss.im>
This commit is contained in:
parent
5553908173
commit
6e3226e2f0
27
benchmarks/performance/filter.bench.ts
Normal file
27
benchmarks/performance/filter.bench.ts
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import { filter as filterToolkit } from 'es-toolkit/compat';
|
||||||
|
import { filter as filterLodash } from 'lodash';
|
||||||
|
import { bench, describe } from 'vitest';
|
||||||
|
|
||||||
|
const arr = [
|
||||||
|
{ a: 0, b: true },
|
||||||
|
{ a: 1, b: true },
|
||||||
|
{ a: 0, b: false },
|
||||||
|
];
|
||||||
|
|
||||||
|
describe('filter', () => {
|
||||||
|
bench('es-toolkit/filter', () => {
|
||||||
|
filterToolkit([1, 2, 3], number => number % 2 === 0);
|
||||||
|
filterToolkit(arr, { b: true });
|
||||||
|
filterToolkit(arr, ['a', 1]);
|
||||||
|
filterToolkit(arr, items => items.b);
|
||||||
|
filterToolkit({ a: 1, b: 2, c: 3 }, 'b');
|
||||||
|
});
|
||||||
|
|
||||||
|
bench('lodash/filter', () => {
|
||||||
|
filterLodash([1, 2, 3], number => number % 2 === 0);
|
||||||
|
filterLodash(arr, { b: true });
|
||||||
|
filterLodash(arr, ['a', 1]);
|
||||||
|
filterLodash(arr, items => items.b);
|
||||||
|
filterLodash({ a: 1, b: 2, c: 3 }, 'b');
|
||||||
|
});
|
||||||
|
});
|
120
docs/ja/reference/compat/array/filter.md
Normal file
120
docs/ja/reference/compat/array/filter.md
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
# filter
|
||||||
|
|
||||||
|
::: info
|
||||||
|
この関数は互換性のために `es-toolkit/compat` からのみインポートできます。代替可能なネイティブ JavaScript API があるか、まだ十分に最適化されていないためです。
|
||||||
|
|
||||||
|
`es-toolkit/compat` からこの関数をインポートすると、[lodash と完全に同じように動作](../../../compatibility.md)します。
|
||||||
|
:::
|
||||||
|
|
||||||
|
与えられた条件を満たす要素を持つ新しい配列を返します。
|
||||||
|
|
||||||
|
条件はいくつかの方法で指定できます。
|
||||||
|
|
||||||
|
- **検査関数**: 各要素に対して検査する関数を実行します。条件に合う要素を選択します。
|
||||||
|
- **部分オブジェクト**: 指定されたオブジェクトと部分的に一致する要素を選択します。
|
||||||
|
- **プロパティ-値ペア**: 指定されたプロパティに対してキーと値が一致する要素を選択します。
|
||||||
|
- **プロパティ名**: 指定されたプロパティ名が存在する要素を選択します。
|
||||||
|
|
||||||
|
## インターフェース
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
function filter<T>(arr: T[], doesMatch: (item: T, index: number, arr: T[]) => unknown): T[];
|
||||||
|
function filter<T>(arr: T[], doesMatch: Partial<T>): T[];
|
||||||
|
function filter<T>(arr: T[], doesMatch: [keyof T, unknown]): T[];
|
||||||
|
function filter<T>(arr: T[], doesMatch: string): T[];
|
||||||
|
|
||||||
|
function filter<T extends Record<string, unknown>>(
|
||||||
|
object: T,
|
||||||
|
doesMatch: (item: T[keyof T], index: number, object: T) => unknown
|
||||||
|
): T[];
|
||||||
|
function filter<T extends Record<string, unknown>>(object: T, doesMatch: Partial<T[keyof T]>): T[];
|
||||||
|
function filter<T extends Record<string, unknown>>(object: T, doesMatch: [keyof T, unknown]): T[];
|
||||||
|
function filter<T extends Record<string, unknown>>(object: T, doesMatch: string): T[];
|
||||||
|
```
|
||||||
|
|
||||||
|
### パラメータ
|
||||||
|
|
||||||
|
- `arr` (`T[]`) または `object` (`T`): 繰り返し処理する配列やオブジェクト。
|
||||||
|
|
||||||
|
- `doesMatch`:
|
||||||
|
|
||||||
|
- 配列の場合:
|
||||||
|
|
||||||
|
- **検査関数** (`(item: T, index: number, arr: T[]) => unknown`): 各要素が条件を満たしているか確認する関数。
|
||||||
|
- **部分オブジェクト** (`Partial<T>`): 要素の属性と値が一致するか確認する部分オブジェクト。
|
||||||
|
- **プロパティ-値ペア** (`[keyof T, unknown]`): 最初の要素が対象プロパティ、2番目が対象値を示すタプル。
|
||||||
|
- **プロパティ名** (`string`): 特定の属性を持っているか確認するプロパティ名。
|
||||||
|
|
||||||
|
- オブジェクトの場合:
|
||||||
|
|
||||||
|
- **検査関数** (`(item: T[keyof T], index: number, object: T) => unknown`): 各要素が条件を満たしているか確認する関数。
|
||||||
|
- **部分値** (`Partial<T[keyof T]>`): 要素の属性と値が一致するか確認する部分オブジェクト。
|
||||||
|
- **プロパティ-値ペア** (`[keyof T, unknown]`): 最初の要素が対象プロパティ、2番目が対象値を示すタプル。
|
||||||
|
- **プロパティ名** (`string`): 特定の属性を持っているか確認するプロパティ名。
|
||||||
|
|
||||||
|
### 戻り値
|
||||||
|
|
||||||
|
(`T[]`): 条件を満たす要素の配列。該当する要素がなければ (`[]`)
|
||||||
|
|
||||||
|
## 例
|
||||||
|
|
||||||
|
### 配列の場合
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { find } from 'es-toolkit/compat';
|
||||||
|
|
||||||
|
// 検査関数を使う場合
|
||||||
|
const items = [1, 2, 3, 4, 5];
|
||||||
|
const result = find(items, item => item > 3);
|
||||||
|
console.log(result); // 4
|
||||||
|
|
||||||
|
// 部分オブジェクトを使う場合
|
||||||
|
const items = [
|
||||||
|
{ id: 1, name: 'Alice' },
|
||||||
|
{ id: 2, name: 'Bob' },
|
||||||
|
];
|
||||||
|
const result = find(items, { name: 'Bob' });
|
||||||
|
console.log(result); // { id: 2, name: 'Bob' }
|
||||||
|
|
||||||
|
// プロパティ-値ペアを使う場合
|
||||||
|
const items = [
|
||||||
|
{ id: 1, name: 'Alice' },
|
||||||
|
{ id: 2, name: 'Bob' },
|
||||||
|
];
|
||||||
|
const result = find(items, ['name', 'Alice']);
|
||||||
|
console.log(result); // { id: 1, name: 'Alice' }
|
||||||
|
|
||||||
|
// プロパティ名を使う場合
|
||||||
|
const items = [
|
||||||
|
{ id: 1, name: 'Alice' },
|
||||||
|
{ id: 2, name: 'Bob' },
|
||||||
|
];
|
||||||
|
const result = find(items, 'name');
|
||||||
|
console.log(result); // { id: 1, name: 'Alice' }
|
||||||
|
```
|
||||||
|
|
||||||
|
### オブジェクトの場合
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { find } from 'es-toolkit/compat';
|
||||||
|
|
||||||
|
// 検査関数を使う場合
|
||||||
|
const obj = { a: 1, b: 2, c: 3 };
|
||||||
|
const result = find(obj, item => item > 2);
|
||||||
|
console.log(result); // 3
|
||||||
|
|
||||||
|
// 部分オブジェクトを使う場合
|
||||||
|
const obj = { a: { id: 1, name: 'Alice' }, b: { id: 2, name: 'Bob' } };
|
||||||
|
const result = find(obj, { name: 'Bob' });
|
||||||
|
console.log(result); // { id: 2, name: 'Bob' }
|
||||||
|
|
||||||
|
// プロパティ-値ペアを使う場合
|
||||||
|
const items = { alice: { id: 1, name: 'Alice' }, bob: { id: 2, name: 'Bob' } };
|
||||||
|
const result = find(items, ['name', 'Alice']);
|
||||||
|
console.log(result); // { id: 1, name: 'Alice' }
|
||||||
|
|
||||||
|
// プロパティ名を使う場合
|
||||||
|
const obj = { a: { id: 1, name: 'Alice' }, b: { id: 2, name: 'Bob' } };
|
||||||
|
const result = find(obj, 'name');
|
||||||
|
console.log(result); // { id: 1, name: 'Alice' }
|
||||||
|
```
|
130
docs/ko/reference/compat/array/filter.md
Normal file
130
docs/ko/reference/compat/array/filter.md
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
# filter
|
||||||
|
|
||||||
|
::: info
|
||||||
|
이 함수는 호환성을 위한 `es-toolkit/compat` 에서만 가져올 수 있어요. 대체할 수 있는 네이티브 JavaScript API가 있거나, 아직 충분히 최적화되지 않았기 때문이에요.
|
||||||
|
|
||||||
|
`es-toolkit/compat`에서 이 함수를 가져오면, [lodash와 완전히 똑같이 동작](../../../compatibility.md)해요.
|
||||||
|
:::
|
||||||
|
|
||||||
|
주어진 조건을 만족하는 요소를 갖는 새로운 배열을 반환해요.
|
||||||
|
|
||||||
|
조건은 여러 방법들로 명시할 수 있어요.
|
||||||
|
|
||||||
|
- **검사 함수**: 각각의 요소에 대해서 검사하는 함수를 실행해요. 조건에 맞는 요소들을 선택해요.
|
||||||
|
- **부분 객체**: 주어진 객체와 부분적으로 일치하는 요소들을 선택해요.
|
||||||
|
- **프로퍼티-값 쌍**: 해당 프로퍼티에 대해서 키와 값이 일치하는 요소들을 선택해요.
|
||||||
|
- **프로퍼티 이름**: 해당 프로퍼티 이름이 일치하는 요소들을 선택해요.
|
||||||
|
|
||||||
|
## 인터페이스
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
function filter<T>(arr: T[], doesMatch: (item: T, index: number, arr: T[]) => unknown): T[];
|
||||||
|
function filter<T>(arr: T[], doesMatch: Partial<T>): T[];
|
||||||
|
function filter<T>(arr: T[], doesMatch: [keyof T, unknown]): T[];
|
||||||
|
function filter<T>(arr: T[], doesMatch: string): T[];
|
||||||
|
|
||||||
|
function filter<T extends Record<string, unknown>>(
|
||||||
|
object: T,
|
||||||
|
doesMatch: (item: T[keyof T], index: number, object: T) => unknown
|
||||||
|
): T[];
|
||||||
|
function filter<T extends Record<string, unknown>>(object: T, doesMatch: Partial<T[keyof T]>): T[];
|
||||||
|
function filter<T extends Record<string, unknown>>(object: T, doesMatch: [keyof T, unknown]): T[];
|
||||||
|
function filter<T extends Record<string, unknown>>(object: T, doesMatch: string): T[];
|
||||||
|
```
|
||||||
|
|
||||||
|
### 파라미터
|
||||||
|
|
||||||
|
- `arr` (`T[]`) or `object` (`T`): 반복할 배열이나 객체.
|
||||||
|
|
||||||
|
- `doesMatch`:
|
||||||
|
|
||||||
|
- 배열의 경우:
|
||||||
|
|
||||||
|
- **검사 함수** (`(item: T, index: number, arr: T[]) => unknown`): 각 요소가 조건을 만족하는지 확인하는 함수.
|
||||||
|
- **부분 객체** (`Partial<T>`): 요소의 속성과 값과 일치하는지 확인할 부분 객체.
|
||||||
|
- **프로퍼티-값 쌍** (`[keyof T, unknown]`): 첫 번째가 찾는 프로퍼티, 두 번째가 찾는 값을 나타내는 튜플.
|
||||||
|
- **프로퍼티 이름** (`string`): 특정 속성을 가지고 있는지 확인할 프로퍼티 이름.
|
||||||
|
|
||||||
|
- 객체의 경우:
|
||||||
|
|
||||||
|
- **검사 함수** (`(item: T[keyof T], index: number, object: T) => unknown`): 각 요소가 조건을 만족하는지 확인하는 함수.
|
||||||
|
- **부분 객체** (`Partial<T[keyof T]>`): 요소의 속성과 값과 일치하는지 확인할 부분 객체.
|
||||||
|
- **프로퍼티-값 쌍** (`[keyof T, unknown]`): 첫 번째가 찾는 프로퍼티, 두 번째가 찾는 값을 나타내는 튜플.
|
||||||
|
- **프로퍼티 이름** (`string`): 특정 속성을 가지고 있는지 확인할 프로퍼티 이름.
|
||||||
|
|
||||||
|
### 반환 값
|
||||||
|
|
||||||
|
(`T[]`): 조건을 만족하는 요소 배열. 없으면 (`[]`)
|
||||||
|
|
||||||
|
## 예시
|
||||||
|
|
||||||
|
### 배열의 경우
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { filter } from 'es-toolkit/compat';
|
||||||
|
|
||||||
|
// 검사 함수를 쓰는 경우
|
||||||
|
filter([1, 2, 3], n => n % 2 === 0);
|
||||||
|
// => [2]
|
||||||
|
|
||||||
|
// 부분 객체를 쓰는 경우
|
||||||
|
const arr = [
|
||||||
|
{ id: 1, name: 'Alice' },
|
||||||
|
{ id: 2, name: 'Bob' },
|
||||||
|
];
|
||||||
|
filter(arr, { name: 'Bob' });
|
||||||
|
// => [{ id: 2, name: 'Bob' }]
|
||||||
|
|
||||||
|
// 프로퍼티-값 쌍을 쓰는 경우
|
||||||
|
const arr = [
|
||||||
|
{ id: 1, name: 'Alice' },
|
||||||
|
{ id: 2, name: 'Bob' },
|
||||||
|
];
|
||||||
|
filter(arr, ['name', 'Alice']);
|
||||||
|
// => [{ id: 1, name: 'Alice' }]
|
||||||
|
|
||||||
|
// 프로퍼티 이름을 쓰는 경우
|
||||||
|
const arr = [
|
||||||
|
{ id: 1, name: 'Alice' },
|
||||||
|
{ id: 2, name: 'Bob' },
|
||||||
|
{ id: 3, age: 28 },
|
||||||
|
];
|
||||||
|
filter(arr, 'name');
|
||||||
|
// => [{ id: 1, name: 'Alice' }]
|
||||||
|
```
|
||||||
|
|
||||||
|
### 객체의 경우
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { filter } from 'es-toolkit/compat';
|
||||||
|
|
||||||
|
// 검사 함수를 쓰는 경우
|
||||||
|
const obj = { a: 1, b: 2, c: 3 };
|
||||||
|
filter(obj, item => item > 2);
|
||||||
|
// => [3]
|
||||||
|
|
||||||
|
// 부분 객체를 쓰는 경우
|
||||||
|
const obj = {
|
||||||
|
a: { id: 1, name: 'Alice' },
|
||||||
|
b: { id: 2, name: 'Bob' },
|
||||||
|
};
|
||||||
|
filter(obj, { name: 'Bob' });
|
||||||
|
// => [{ id: 2, name: 'Bob' }]
|
||||||
|
|
||||||
|
// 프로퍼티-값 쌍을 쓰는 경우
|
||||||
|
const obj = {
|
||||||
|
alice: { id: 1, name: 'Alice' },
|
||||||
|
bob: { id: 2, name: 'Bob' },
|
||||||
|
};
|
||||||
|
filter(obj, ['name', 'Alice']);
|
||||||
|
// => [{ id: 1, name: 'Alice' }]
|
||||||
|
|
||||||
|
// 프로퍼티 이름을 쓰는 경우
|
||||||
|
const obj = {
|
||||||
|
a: { id: 1, name: 'Alice' },
|
||||||
|
b: { id: 2, name: 'Bob' },
|
||||||
|
c: { id: 3, age: 28 },
|
||||||
|
};
|
||||||
|
filter(obj, 'name');
|
||||||
|
// => [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }]
|
||||||
|
```
|
129
docs/reference/compat/array/filter.md
Normal file
129
docs/reference/compat/array/filter.md
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
# filter
|
||||||
|
|
||||||
|
::: info
|
||||||
|
This function is only available in `es-toolkit/compat` for compatibility reasons. It either has alternative native JavaScript APIs or isn’t fully optimized yet.
|
||||||
|
|
||||||
|
When imported from `es-toolkit/compat`, it behaves exactly like lodash and provides the same functionalities, as detailed [here](../../../compatibility.md).
|
||||||
|
:::
|
||||||
|
|
||||||
|
Returns a new array of elements that satisfy the provided condition.
|
||||||
|
|
||||||
|
The condition can be specified in several ways:
|
||||||
|
|
||||||
|
- **Predicate function**: Runs a function for each element, selecting elements that satisfy the condition.
|
||||||
|
- **Partial object**: Selects elements that partially match the provided object.
|
||||||
|
- **Property-value pair**: Selects elements where a specified key matches a given value.
|
||||||
|
- **Property name**: Selects elements where the specified property name exists.
|
||||||
|
|
||||||
|
## Signature
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
function filter<T>(arr: T[], doesMatch: (item: T, index: number, arr: T[]) => unknown): T[];
|
||||||
|
function filter<T>(arr: T[], doesMatch: Partial<T>): T[];
|
||||||
|
function filter<T>(arr: T[], doesMatch: [keyof T, unknown]): T[];
|
||||||
|
function filter<T>(arr: T[], doesMatch: string): T[];
|
||||||
|
|
||||||
|
function filter<T extends Record<string, unknown>>(
|
||||||
|
object: T,
|
||||||
|
doesMatch: (item: T[keyof T], index: number, object: T) => unknown
|
||||||
|
): T[];
|
||||||
|
function filter<T extends Record<string, unknown>>(object: T, doesMatch: Partial<T[keyof T]>): T[];
|
||||||
|
function filter<T extends Record<string, unknown>>(object: T, doesMatch: [keyof T, unknown]): T[];
|
||||||
|
function filter<T extends Record<string, unknown>>(object: T, doesMatch: string): T[];
|
||||||
|
```
|
||||||
|
|
||||||
|
### Parameters
|
||||||
|
|
||||||
|
- `arr` (`T[]`) or `object` (`T`): The array or object to iterate over.
|
||||||
|
|
||||||
|
- `doesMatch`:
|
||||||
|
|
||||||
|
- For the first `filter` overload with arrays:
|
||||||
|
|
||||||
|
- **Predicate function** (`(item: T, index: number, arr: T[]) => unknown`): A function to check if an element satisfies a condition.
|
||||||
|
- **Partial object** (`Partial<T>`): A partial object that specifies the properties to match.
|
||||||
|
- **Property-value pair** (`[keyof T, unknown]`): An array where the first element is the property key and the second element is the value to match.
|
||||||
|
- **Property name** (`string`): The name of the property to check for in the elements.
|
||||||
|
|
||||||
|
- For the `filter` overloads with objects:
|
||||||
|
- **Predicate function** (`(item: T[keyof T], index: number, object: T) => unknown`): A function that takes an item, its key, and the object, and returns a truthy value if the item matches the criteria.
|
||||||
|
- **Partial value** (`Partial<T[keyof T]>`): A partial value to match against the values of the object.
|
||||||
|
- **Property-value pair** (`[keyof T, unknown]`): An array where the first element is the property key and the second element is the value to match.
|
||||||
|
- **Property name** (`string`): The name of the property to check for a truthy value.
|
||||||
|
|
||||||
|
### Returns
|
||||||
|
|
||||||
|
(`T[]`): An array of elements that satisfy the condition. If none, an empty array. (`[]`)
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
### Array
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { filter } from 'es-toolkit/compat';
|
||||||
|
|
||||||
|
// Using a predicate function
|
||||||
|
filter([1, 2, 3], n => n % 2 === 0);
|
||||||
|
// => [2]
|
||||||
|
|
||||||
|
// Using a partial object
|
||||||
|
const arr = [
|
||||||
|
{ id: 1, name: 'Alice' },
|
||||||
|
{ id: 2, name: 'Bob' },
|
||||||
|
];
|
||||||
|
filter(arr, { name: 'Bob' });
|
||||||
|
// => [{ id: 2, name: 'Bob' }]
|
||||||
|
|
||||||
|
// Using a property-value pair
|
||||||
|
const arr = [
|
||||||
|
{ id: 1, name: 'Alice' },
|
||||||
|
{ id: 2, name: 'Bob' },
|
||||||
|
];
|
||||||
|
filter(arr, ['name', 'Alice']);
|
||||||
|
// => [{ id: 1, name: 'Alice' }]
|
||||||
|
|
||||||
|
// Using a property name
|
||||||
|
const arr = [
|
||||||
|
{ id: 1, name: 'Alice' },
|
||||||
|
{ id: 2, name: 'Bob' },
|
||||||
|
{ id: 3, age: 28 },
|
||||||
|
];
|
||||||
|
filter(arr, 'name');
|
||||||
|
// => [{ id: 1, name: 'Alice' }]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Object
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { filter } from 'es-toolkit/compat';
|
||||||
|
|
||||||
|
// Using a predicate function
|
||||||
|
const obj = { a: 1, b: 2, c: 3 };
|
||||||
|
filter(obj, item => item > 2);
|
||||||
|
// => [3]
|
||||||
|
|
||||||
|
// Using a partial object
|
||||||
|
const obj = {
|
||||||
|
a: { id: 1, name: 'Alice' },
|
||||||
|
b: { id: 2, name: 'Bob' },
|
||||||
|
};
|
||||||
|
filter(obj, { name: 'Bob' });
|
||||||
|
// => [{ id: 2, name: 'Bob' }]
|
||||||
|
|
||||||
|
// Using a property-value pair
|
||||||
|
const obj = {
|
||||||
|
alice: { id: 1, name: 'Alice' },
|
||||||
|
bob: { id: 2, name: 'Bob' },
|
||||||
|
};
|
||||||
|
filter(obj, ['name', 'Alice']);
|
||||||
|
// => [{ id: 1, name: 'Alice' }]
|
||||||
|
|
||||||
|
// Using a property name
|
||||||
|
const obj = {
|
||||||
|
a: { id: 1, name: 'Alice' },
|
||||||
|
b: { id: 2, name: 'Bob' },
|
||||||
|
c: { id: 3, age: 28 },
|
||||||
|
};
|
||||||
|
filter(obj, 'name');
|
||||||
|
// => [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }]
|
||||||
|
```
|
130
docs/zh_hans/reference/compat/array/filter.md
Normal file
130
docs/zh_hans/reference/compat/array/filter.md
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
# filter
|
||||||
|
|
||||||
|
::: info
|
||||||
|
出于兼容性原因,此函数仅在 `es-toolkit/compat` 中提供。它可能具有替代的原生 JavaScript API,或者尚未完全优化。
|
||||||
|
|
||||||
|
从 `es-toolkit/compat` 导入时,它的行为与 lodash 完全一致,并提供相同的功能,详情请见 [这里](../../../compatibility.md)。
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
返回满足提供条件的元素新数组。
|
||||||
|
|
||||||
|
条件可以通过多种方式指定:
|
||||||
|
|
||||||
|
- **谓词函数**: 对每个元素执行一个函数,选择满足条件的元素。
|
||||||
|
- **部分对象**: 选择与提供的对象部分匹配的元素。
|
||||||
|
- **属性-值对**: 选择指定键与给定值匹配的元素。
|
||||||
|
- **属性名称**: 选择存在指定属性名的元素。
|
||||||
|
|
||||||
|
## 签名
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
function filter<T>(arr: T[], doesMatch: (item: T, index: number, arr: T[]) => unknown): T[];
|
||||||
|
function filter<T>(arr: T[], doesMatch: Partial<T>): T[];
|
||||||
|
function filter<T>(arr: T[], doesMatch: [keyof T, unknown]): T[];
|
||||||
|
function filter<T>(arr: T[], doesMatch: string): T[];
|
||||||
|
|
||||||
|
function filter<T extends Record<string, unknown>>(
|
||||||
|
object: T,
|
||||||
|
doesMatch: (item: T[keyof T], index: number, object: T) => unknown
|
||||||
|
): T[];
|
||||||
|
function filter<T extends Record<string, unknown>>(object: T, doesMatch: Partial<T[keyof T]>): T[];
|
||||||
|
function filter<T extends Record<string, unknown>>(object: T, doesMatch: [keyof T, unknown]): T[];
|
||||||
|
function filter<T extends Record<string, unknown>>(object: T, doesMatch: string): T[];
|
||||||
|
```
|
||||||
|
|
||||||
|
### 参数
|
||||||
|
|
||||||
|
- `arr` (`T[]`) 或 `object` (`T`): 要迭代的数组或对象。
|
||||||
|
|
||||||
|
- `doesMatch`:
|
||||||
|
|
||||||
|
- 对于数组的第一个 `filter` 重载:
|
||||||
|
|
||||||
|
- **谓词函数** (`(item: T, index: number, arr: T[]) => unknown`): 一个检查元素是否满足条件的函数。
|
||||||
|
- **部分对象** (`Partial<T>`): 用于检查元素的属性和值是否匹配的部分对象。
|
||||||
|
- **属性-值对** (`[keyof T, unknown]`): 一个数组,第一个元素是属性键,第二个元素是要匹配的值。
|
||||||
|
- **属性名称** (`string`): 用于检查是否具有特定属性的属性名称。
|
||||||
|
|
||||||
|
- 对于对象的 `filter` 重载:
|
||||||
|
- **谓词函数** (`(item: T[keyof T], index: number, object: T) => unknown`): 一个函数,接收一个项、其键和对象,如果该项符合条件,则返回一个真值。
|
||||||
|
- **部分值** (`Partial<T[keyof T]>`): 用于检查元素的属性和值是否匹配的部分对象。
|
||||||
|
- **属性-值对** (`[keyof T, unknown]`): 一个数组,第一个元素是属性键,第二个元素是要匹配的值。
|
||||||
|
- **属性名称** (`string`): 用于检查是否具有特定属性的属性名称。
|
||||||
|
|
||||||
|
### 返回
|
||||||
|
|
||||||
|
(`T[]`): 满足条件的元素数组。如果没有,返回空数组。 (`[]`)
|
||||||
|
|
||||||
|
## 示例
|
||||||
|
|
||||||
|
### 数组
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { filter } from 'es-toolkit/compat';
|
||||||
|
|
||||||
|
// 使用谓词函数
|
||||||
|
filter([1, 2, 3], n => n % 2 === 0);
|
||||||
|
// => [2]
|
||||||
|
|
||||||
|
// 使用部分对象
|
||||||
|
const arr = [
|
||||||
|
{ id: 1, name: 'Alice' },
|
||||||
|
{ id: 2, name: 'Bob' },
|
||||||
|
];
|
||||||
|
filter(arr, { name: 'Bob' });
|
||||||
|
// => [{ id: 2, name: 'Bob' }]
|
||||||
|
|
||||||
|
// 使用属性-值对
|
||||||
|
const arr = [
|
||||||
|
{ id: 1, name: 'Alice' },
|
||||||
|
{ id: 2, name: 'Bob' },
|
||||||
|
];
|
||||||
|
filter(arr, ['name', 'Alice']);
|
||||||
|
// => [{ id: 1, name: 'Alice' }]
|
||||||
|
|
||||||
|
// 使用属性名称
|
||||||
|
const arr = [
|
||||||
|
{ id: 1, name: 'Alice' },
|
||||||
|
{ id: 2, name: 'Bob' },
|
||||||
|
{ id: 3, age: 28 },
|
||||||
|
];
|
||||||
|
filter(arr, 'name');
|
||||||
|
// => [{ id: 1, name: 'Alice' }]
|
||||||
|
```
|
||||||
|
|
||||||
|
### 对象
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { filter } from 'es-toolkit/compat';
|
||||||
|
|
||||||
|
// 使用谓词函数
|
||||||
|
const obj = { a: 1, b: 2, c: 3 };
|
||||||
|
filter(obj, item => item > 2);
|
||||||
|
// => [3]
|
||||||
|
|
||||||
|
// 使用部分对象
|
||||||
|
const obj = {
|
||||||
|
a: { id: 1, name: 'Alice' },
|
||||||
|
b: { id: 2, name: 'Bob' },
|
||||||
|
};
|
||||||
|
filter(obj, { name: 'Bob' });
|
||||||
|
// => [{ id: 2, name: 'Bob' }]
|
||||||
|
|
||||||
|
// 使用属性-值对
|
||||||
|
const obj = {
|
||||||
|
alice: { id: 1, name: 'Alice' },
|
||||||
|
bob: { id: 2, name: 'Bob' },
|
||||||
|
};
|
||||||
|
filter(obj, ['name', 'Alice']);
|
||||||
|
// => [{ id: 1, name: 'Alice' }]
|
||||||
|
|
||||||
|
// 使用属性名称
|
||||||
|
const obj = {
|
||||||
|
a: { id: 1, name: 'Alice' },
|
||||||
|
b: { id: 2, name: 'Bob' },
|
||||||
|
c: { id: 3, age: 28 },
|
||||||
|
};
|
||||||
|
filter(obj, 'name');
|
||||||
|
// => [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }]
|
||||||
|
```
|
115
src/compat/array/filter.spec.ts
Normal file
115
src/compat/array/filter.spec.ts
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
import { describe, expect, it } from 'vitest';
|
||||||
|
import { filter } from './filter';
|
||||||
|
|
||||||
|
function isEven(n: number) {
|
||||||
|
return n % 2 === 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('filter', () => {
|
||||||
|
it('It should return an empty array when no predicate is provided.', () => {
|
||||||
|
const arr = [1, 2, 3];
|
||||||
|
|
||||||
|
expect(filter(arr)).toEqual([1, 2, 3]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return an array of elements from the array', () => {
|
||||||
|
const arr = [1, 2, 3];
|
||||||
|
|
||||||
|
expect(filter(arr, isEven)).toEqual([2]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it(`filter should work with \`matches\` shorthands`, () => {
|
||||||
|
const arr = [
|
||||||
|
{ id: 1, name: 'Alice' },
|
||||||
|
{ id: 2, name: 'Bob' },
|
||||||
|
];
|
||||||
|
expect(filter(arr, { name: 'Bob' })).toEqual([{ id: 2, name: 'Bob' }]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it(`filter should work with \`matchesProperty\` shorthands`, () => {
|
||||||
|
const arr = [
|
||||||
|
{ id: 1, name: 'Alice' },
|
||||||
|
{ id: 2, name: 'Bob' },
|
||||||
|
];
|
||||||
|
|
||||||
|
expect(filter(arr, ['name', 'Alice'])).toEqual([{ id: 1, name: 'Alice' }]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it(`filter should work with \`property\` shorthands`, () => {
|
||||||
|
const arr = [
|
||||||
|
{ id: 1, name: 'Alice' },
|
||||||
|
{ id: 2, name: 'Bob' },
|
||||||
|
{ id: 3, age: 28 },
|
||||||
|
];
|
||||||
|
|
||||||
|
expect(filter(arr, 'name')).toEqual([
|
||||||
|
{ id: 1, name: 'Alice' },
|
||||||
|
{ id: 2, name: 'Bob' },
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it(`should return an array of elements from the object`, () => {
|
||||||
|
const obj: { [key: string]: number } = {
|
||||||
|
a: 1,
|
||||||
|
b: 2,
|
||||||
|
c: 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(filter(obj, item => item > 2)).toEqual([3]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it(`filter should work with \`matches\` shorthands for objects.`, () => {
|
||||||
|
const obj = {
|
||||||
|
item1: { a: 0 },
|
||||||
|
item2: { a: 1 },
|
||||||
|
item3: { a: 2 },
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(filter(obj, { a: 1 })).toEqual([{ a: 1 }]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it(`filter should work with \`matches\` shorthands for nested objects.`, () => {
|
||||||
|
const obj = {
|
||||||
|
item1: { a: 0, b: { c: 1 } },
|
||||||
|
item2: { a: 1, b: { c: 2 } },
|
||||||
|
item3: { a: 0, b: { c: 1 } },
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(filter(obj, { b: { c: 1 } })).toEqual([
|
||||||
|
{ a: 0, b: { c: 1 } },
|
||||||
|
{ a: 0, b: { c: 1 } },
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it(`filter should work when looking for values inside nested objects`, () => {
|
||||||
|
const obj: Record<string, unknown> = {
|
||||||
|
item1: { a: 0, b: { c: 1 } },
|
||||||
|
item2: { a: 1, b: { c: 2 } },
|
||||||
|
item3: { a: 0, b: { c: 1 } },
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(filter(obj, ['b.c', 2])).toEqual([{ a: 1, b: { c: 2 } }]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('filter should match nested object properties using key-value pair shorthand.', () => {
|
||||||
|
const obj: { [key: string]: { [key: string]: unknown } } = {
|
||||||
|
alice: { id: 1, name: 'Alice' },
|
||||||
|
bob: { id: 2, name: 'Bob' },
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(filter(obj, ['name', 'Alice'])).toEqual([{ id: 1, name: 'Alice' }]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('filter should return objects that have the specified key.', () => {
|
||||||
|
const obj: { [key: string]: { [key: string]: unknown } } = {
|
||||||
|
a: { id: 1, name: 'Alice' },
|
||||||
|
b: { id: 2, name: 'Bob' },
|
||||||
|
c: { id: 3, age: 28 },
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(filter(obj, 'name')).toEqual([
|
||||||
|
{ id: 1, name: 'Alice' },
|
||||||
|
{ id: 2, name: 'Bob' },
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
});
|
179
src/compat/array/filter.ts
Normal file
179
src/compat/array/filter.ts
Normal file
@ -0,0 +1,179 @@
|
|||||||
|
import { identity } from '../_internal/identity';
|
||||||
|
import { property } from '../object/property';
|
||||||
|
import { isArray } from '../predicate/isArray';
|
||||||
|
import { matches } from '../predicate/matches';
|
||||||
|
import { matchesProperty } from '../predicate/matchesProperty';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filters items from a array and returns an array of elements.
|
||||||
|
*
|
||||||
|
* @template T
|
||||||
|
* @param {T[]} arr - The array to iterate over.
|
||||||
|
* @param {(item: T, index: number, arr: T[]) => unknown} doesMatch - The function invoked per iteration.
|
||||||
|
* @returns {T[]} - Returns a new array of elements that satisfy the given doesMatch function.
|
||||||
|
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* filter([1, 2, 3], n => n % 2 === 0)
|
||||||
|
* // => [2]
|
||||||
|
*/
|
||||||
|
export function filter<T>(arr: readonly T[], doesMatch?: (item: T, index: number, arr: readonly T[]) => unknown): T[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filters elements in a arr that match the properties of the given partial object.
|
||||||
|
*
|
||||||
|
* @template T
|
||||||
|
* @param {T[]} arr - The array to iterate over.
|
||||||
|
* @param {Partial<T>} doesMatch - A partial object that specifies the properties to match.
|
||||||
|
* @returns {T[]} - Returns a new array of elements that match the given properties.
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* const arr = [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }];
|
||||||
|
* filter(arr, { name: 'Bob' });
|
||||||
|
* // => [{ id: 2, name: 'Bob' }]
|
||||||
|
*/
|
||||||
|
export function filter<T>(arr: readonly T[], doesMatch: Partial<T>): T[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filters elements in a arr that match the given key-value pair.
|
||||||
|
*
|
||||||
|
* @template T
|
||||||
|
* @param {readonly T[]} arr - The array to iterate over.
|
||||||
|
* @param {[keyof T, unknown]} doesMatchProperty - The key-value pair to match.
|
||||||
|
* @returns {T[]} - Returns a new array of elements that match the given key-value pair.
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* const arr = [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }];
|
||||||
|
* filter(arr, ['name', 'Alice']);
|
||||||
|
* // => [{ id: 1, name: 'Alice' }]
|
||||||
|
*/
|
||||||
|
export function filter<T>(arr: readonly T[], doesMatchProperty: [keyof T, unknown]): T[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filters the arr, returning elements that contain the given property name.
|
||||||
|
*
|
||||||
|
* @template T
|
||||||
|
* @param {readonly T[]} arr - The array to iterate over.
|
||||||
|
* @param {string} propertyToCheck - The property name to check.
|
||||||
|
* @returns {T[]} - Returns a new array of elements that match the given property name.
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* const arr = [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }, { id: 3, age: 28 }];
|
||||||
|
* filter(arr, 'name');
|
||||||
|
* // => [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }]
|
||||||
|
*/
|
||||||
|
export function filter<T>(arr: readonly T[], propertyToCheck: string): T[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filters items from a object and returns an array of elements that match the given predicate function.
|
||||||
|
*
|
||||||
|
* @template T
|
||||||
|
* @param {T extends Record<string, unknown> ? T : never} object - The object to iterate over.
|
||||||
|
* @param {(item: T[keyof T], index: number, arr: T) => unknown} doesMatch - The function invoked per iteration.
|
||||||
|
* @returns {T[]} - Returns a new array of elements that satisfy the given predicate function.
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* const obj = { item1: { a: 0 }, item2: { a: 1 }, item3: { a: 0 } }
|
||||||
|
* filter(obj, items => items.a)
|
||||||
|
* // => [{ a: 1 }]
|
||||||
|
*
|
||||||
|
* const obj = { a: 1, b: 2, c: 3 };
|
||||||
|
* filter(obj, item => item > 2)
|
||||||
|
* // => [3]
|
||||||
|
*/
|
||||||
|
export function filter<T extends Record<string, unknown>>(
|
||||||
|
object: T,
|
||||||
|
doesMatch: (item: T[keyof T], index: number, object: T) => unknown
|
||||||
|
): T[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filters elements in a object that match the properties of the given partial object.
|
||||||
|
*
|
||||||
|
* @template T
|
||||||
|
* @param {T extends Record<string, unknown> ? T : never} object - The object to iterate over.
|
||||||
|
* @param {Partial<T[keyof T]>} doesMatch - The partial object to match
|
||||||
|
* @returns {T[]} - Returns a new array of elements that match the given properties.pair.
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* const obj = { a: { id: 1, name: 'Alice' }, b: { id: 2, name: 'Bob' } };
|
||||||
|
* filter(obj, { name: 'Bob' });
|
||||||
|
* // => [{ id: 2, name: 'Bob' }]
|
||||||
|
*/
|
||||||
|
export function filter<T extends Record<string, unknown>>(object: T, doesMatch: Partial<T[keyof T]>): T[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filters elements in a arr that match the given key-value pair.
|
||||||
|
*
|
||||||
|
* @template T
|
||||||
|
* @param {T extends Record<string, unknown> ? T : never} object - The object to iterate over.
|
||||||
|
* @param {[keyof T, unknown]} doesMatchProperty - The key-value pair to match.
|
||||||
|
* @returns {T[]} - Returns a new array of elements that match the given key-value pair.
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* const obj = { alice: { id: 1, name: 'Alice' }, bob: { id: 2, name: 'Bob' } };
|
||||||
|
* filter(obj, ['name', 'Alice']);
|
||||||
|
* // => [{ id: 1, name: 'Alice' }]
|
||||||
|
*/
|
||||||
|
export function filter<T extends Record<string, unknown>>(object: T, doesMatchProperty: [keyof T, unknown]): T[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filters the object, returning elements that contain the given property name.
|
||||||
|
*
|
||||||
|
* @template T
|
||||||
|
* @param {T extends Record<string, unknown> ? T : never} object - The object to iterate over.
|
||||||
|
* @param {string} propertyToCheck - The property name to check.
|
||||||
|
* @returns {T[]} - Returns a new array of elements that match the given property name.
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* const obj = { a: { id: 1, name: 'Alice' }, b: { id: 2, name: 'Bob' }, c: { id: 3, age: 28 } };
|
||||||
|
* filter(obj, 'name');
|
||||||
|
* // => [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }]
|
||||||
|
*/
|
||||||
|
export function filter<T extends Record<string, unknown>>(object: T, propertyToCheck: string): T[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Iterates over the collection and filters elements based on the given predicate.
|
||||||
|
* If a function is provided, it is invoked for each element in the collection.
|
||||||
|
*
|
||||||
|
* @template T
|
||||||
|
* @param {readonly T[] | Record<any, any>} source - The array or object to iterate over.
|
||||||
|
* @param {((item: T, index: number, arr: any) => unknown) | Partial<T> | [keyof T, unknown] | string} [predicate=identity] - The function invoked per iteration.
|
||||||
|
* @returns {T[]} - Returns a new array of filtered elements that satisfy the predicate.
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* filter([{ a: 1 }, { a: 2 }, { b: 1 }], 'a');
|
||||||
|
* // => [{ a: 1 }, { a: 2 }]
|
||||||
|
*
|
||||||
|
* filter([{ a: 1 }, { a: 2 }, { b: 1 }], { b: 1 });
|
||||||
|
* // => [{ b: 1 }]
|
||||||
|
*
|
||||||
|
* filter({ item1: { a: 0, b: true }, item2: { a: 1, b: true }, item3: { a: 2, b: false }}, { b: false })
|
||||||
|
* // => [{ a: 2, b: false }]
|
||||||
|
*
|
||||||
|
* filter([{ a: 1 }, { a: 2 }, { a: 3 }], ['a', 2]);
|
||||||
|
* // => [{ a: 2 }]
|
||||||
|
*/
|
||||||
|
export function filter<T>(
|
||||||
|
source: T[] | Record<any, any>,
|
||||||
|
predicate?: ((item: T, index: number, arr: any) => unknown) | Partial<T> | [keyof T, unknown] | string
|
||||||
|
): T[] {
|
||||||
|
if (!predicate) {
|
||||||
|
predicate = identity;
|
||||||
|
}
|
||||||
|
|
||||||
|
const collection = isArray(source) ? source : Object.values(source);
|
||||||
|
|
||||||
|
switch (typeof predicate) {
|
||||||
|
case 'function': {
|
||||||
|
return collection.filter(predicate);
|
||||||
|
}
|
||||||
|
case 'object': {
|
||||||
|
return isArray(predicate)
|
||||||
|
? collection.filter(matchesProperty(predicate[0], predicate[1]))
|
||||||
|
: collection.filter(matches(predicate));
|
||||||
|
}
|
||||||
|
case 'string': {
|
||||||
|
return collection.filter(property(predicate));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -45,6 +45,7 @@ export { sortBy } from './array/sortBy.ts';
|
|||||||
export { size } from './array/size.ts';
|
export { size } from './array/size.ts';
|
||||||
export { some } from './array/some.ts';
|
export { some } from './array/some.ts';
|
||||||
export { zipObjectDeep } from './array/zipObjectDeep.ts';
|
export { zipObjectDeep } from './array/zipObjectDeep.ts';
|
||||||
|
export { filter } from './array/filter.ts';
|
||||||
export { head as first } from '../array/head.ts';
|
export { head as first } from '../array/head.ts';
|
||||||
|
|
||||||
export { ary } from './function/ary.ts';
|
export { ary } from './function/ary.ts';
|
||||||
|
Loading…
Reference in New Issue
Block a user