Skip to content

Commit

Permalink
feat: add pick, omit, pickBy, and omitBy functions
Browse files Browse the repository at this point in the history
  • Loading branch information
Aybrea committed Nov 5, 2024
1 parent 5c4a942 commit cbd913c
Show file tree
Hide file tree
Showing 11 changed files with 385 additions and 1 deletion.
4 changes: 4 additions & 0 deletions docs/.vitepress/items/collection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,8 @@ export const collectionItems = [
{ text: 'cloneDeepWith', link: '/collection/clone-deep-with' },
{ text: 'merge', link: '/collection/merge' },
{ text: 'mergeWith', link: '/collection/merge-with' },
{ text: 'pick', link: '/collection/pick' },
{ text: 'pickBy', link: '/collection/pick-by' },
{ text: 'omit', link: '/collection/omit' },
{ text: 'omitBy', link: '/collection/omit-by' },
]
25 changes: 25 additions & 0 deletions docs/collection/omit-by.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# omitBy

Creates a new object by omitting key-value pairs based on a predicate function.

### Usage

```ts
import { omitBy } from 'rattail'

omitBy({ a: 1, b: 2, c: 3 }, (value) => value > 1)
// return { a: 1 }
```

### Arguments

| Arg | Type | Defaults |
| -------- | -------------------------------------- | -------- |
| `object` | `object` | |
| `fn` | `(value: any, key: string) => boolean` | |

### Return

| Type |
| -------- |
| `object` |
25 changes: 25 additions & 0 deletions docs/collection/omit.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# omit

Creates a new object by omitting specified keys from an existing object.

### Usage

```ts
import { omit } from 'rattail'

omit({ a: 1, b: 2, c: 3 }, ['a', 'c'])
// return { b: 2 }
```

### Arguments

| Arg | Type | Defaults |
| -------- | ---------- | -------- |
| `object` | `object` | |
| `keys` | `string[]` | |

### Return

| Type |
| -------- |
| `object` |
25 changes: 25 additions & 0 deletions docs/collection/pick-by.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# pickBy

Creates a new object by picking key-value pairs based on a predicate function.

### Usage

```ts
import { pickBy } from 'rattail'

pickBy({ a: 1, b: 2, c: 3 }, (value) => value > 1)
// return { b: 2, c: 3 }
```

### Arguments

| Arg | Type | Defaults |
| -------- | -------------------------------------- | -------- |
| `object` | `object` | |
| `fn` | `(value: any, key: string) => boolean` | |

### Return

| Type |
| -------- |
| `object` |
25 changes: 25 additions & 0 deletions docs/collection/pick.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# pick

Creates a new object by selecting specified keys from an existing object.

### Usage

```ts
import { pick } from 'rattail'

pick({ a: 1, b: 2, c: 3 }, ['a', 'c'])
// return { a: 1, c: 3 }
```

### Arguments

| Arg | Type | Defaults |
| -------- | ---------- | -------- |
| `object` | `object` | |
| `keys` | `string[]` | |

### Return

| Type |
| -------- |
| `object` |
25 changes: 25 additions & 0 deletions docs/zh/collection/omit-by.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# omitBy

通过提供的谓词函数排除键值对来创建新对象。

### 使用

```ts
import { omitBy } from 'rattail'

omitBy({ a: 1, b: 2, c: 3 }, (value) => value > 1)
// return { a: 1 }
```

### 参数

| 参数 | 类型 | 默认值 |
| -------- | -------------------------------------- | ------ |
| `object` | `object` | |
| `fn` | `(value: any, key: string) => boolean` | |

### 返回值

| 类型 |
| -------- |
| `object` |
25 changes: 25 additions & 0 deletions docs/zh/collection/omit.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# omit

通过从现有对象中排除指定键来创建新对象。

### 使用

```ts
import { omit } from 'rattail'

omit({ a: 1, b: 2, c: 3 }, ['a', 'c'])
// return { b: 2 }
```

### 参数

| 参数 | 类型 | 默认值 |
| -------- | ---------- | ------ |
| `object` | `object` | |
| `keys` | `string[]` | |

### 返回值

| 类型 |
| -------- |
| `object` |
25 changes: 25 additions & 0 deletions docs/zh/collection/pick-by.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# pickBy

通过提供的谓词函数选择键值对来创建新对象。

### 使用

```ts
import { pickBy } from 'rattail'

pickBy({ a: 1, b: 2, c: 3 }, (value) => value > 1)
// return { b: 2, c: 3 }
```

### 参数

| 参数 | 类型 | 默认值 |
| -------- | -------------------------------------- | ------ |
| `object` | `object` | |
| `fn` | `(value: any, key: string) => boolean` | |

### 返回值

| 类型 |
| -------- |
| `object` |
25 changes: 25 additions & 0 deletions docs/zh/collection/pick.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# pick

通过从现有对象中选择指定键来创建新对象。

### 使用

```ts
import { pick } from 'rattail'

pick({ a: 1, b: 2, c: 3 }, ['a', 'c'])
// return { a: 1, c: 3 }
```

### 参数

| 参数 | 类型 | 默认值 |
| -------- | ---------- | ------ |
| `object` | `object` | |
| `keys` | `string[]` | |

### 返回值

| 类型 |
| -------- |
| `object` |
69 changes: 69 additions & 0 deletions src/collection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,3 +167,72 @@ export function cloneDeepWith<T>(value: T, fn: (value: any) => any): T {

return baseCloneDeep(value, cache)
}

export function pick<T, K extends keyof T>(object: T, keys: K[]): Pick<T, K> {
return keys.reduce(
(result, key) => {
result[key] = object[key]
return result
},
{} as Pick<T, K>,
)
}

export function pickBy<T>(
collection: T,
fn: (value: T extends any[] ? T[number] : T[keyof T], key: keyof T | number) => boolean,
): Partial<T> | T[] | undefined {
if (Array.isArray(collection)) {
return collection.reduce((result, value, index) => {
if (fn(value as T extends any[] ? T[number] : T[keyof T], index)) {
;(result as T[]).push(value)
}
return result
}, [] as T[])
}

if (typeof collection === 'object' && collection !== null) {
const allKeys = [...Object.keys(collection), ...Object.getOwnPropertySymbols(collection)] as (keyof T)[]
return allKeys.reduce((result, key) => {
const value = collection[key as keyof T]
if (fn(value as T extends any[] ? T[number] : T[keyof T], key)) {
;(result as Partial<T>)[key] = value
}
return result
}, {} as Partial<T>)
}
}

export function omit<T extends object, K extends keyof T>(object: T, keys: K[]): Omit<T, K> {
const keysToOmit = new Set(keys)
const result = {} as Omit<T, K>
const ownKeys = [...Object.keys(object), ...Object.getOwnPropertySymbols(object)] as (keyof T)[]

ownKeys.forEach((key) => {
if (!keysToOmit.has(key as K)) {
;(result as T)[key] = object[key]
}
})

return result
}

export function omitBy<T>(
collection: T,
fn: (value: T extends any[] ? T[number] : T[keyof T], key: number | keyof T) => boolean,
): Partial<T> | T[] | undefined {
if (Array.isArray(collection)) {
return collection.filter((value, index) => !fn(value as T extends any[] ? T[number] : T[keyof T], index))
}

if (typeof collection === 'object' && collection !== null) {
const allKeys = [...Object.keys(collection), ...Object.getOwnPropertySymbols(collection)] as (keyof T)[]
return allKeys.reduce((result, key) => {
const value = collection[key]
if (!fn(value as T extends any[] ? T[number] : T[keyof T], key)) {
;(result as Partial<T>)[key] = value
}
return result
}, {} as Partial<T>)
}
}
Loading

0 comments on commit cbd913c

Please sign in to comment.