Skip to content

Commit

Permalink
feat: add pick, omit, pickBy, and omitBy functions (#27)
Browse files Browse the repository at this point in the history
* chore: delete excessive exports

* feat: add pick, omit, pickBy, and omitBy functions
  • Loading branch information
Aybrea authored Nov 7, 2024
1 parent d997edc commit ee83029
Show file tree
Hide file tree
Showing 14 changed files with 371 additions and 3 deletions.
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` |
19 changes: 19 additions & 0 deletions src/collection/omit-by.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
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>)
}
}
15 changes: 15 additions & 0 deletions src/collection/omit.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
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>
console.log(Object.keys(object))

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
}
12 changes: 12 additions & 0 deletions src/collection/pick-by.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export function pickBy<T>(collection: T, fn: (value: any, key: keyof T) => boolean): Partial<T> | undefined {
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, key)) {
;(result as Partial<T>)[key] = value
}
return result
}, {} as Partial<T>)
}
}
9 changes: 9 additions & 0 deletions src/collection/pick.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
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>,
)
}
2 changes: 0 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,3 @@ export * from './string'
export * from './collection'
export * from './file'
export * from './math'
export * from 'mitt'
export { default as mitt } from 'mitt'
117 changes: 116 additions & 1 deletion tests/collection.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { describe, it, expect } from 'vitest'
import { merge, mergeWith, cloneDeep, cloneDeepWith, isNumber, hasOwn } from '../src'
import { merge, mergeWith, cloneDeep, cloneDeepWith, isNumber, hasOwn, pick, omit, pickBy, omitBy } from '../src'

it('should merge two objects', () => {
const result = merge({ a: 1, b: { c: 2 } }, { b: { d: 3 }, e: 4 })
Expand Down Expand Up @@ -344,3 +344,118 @@ describe('cloneDeepWith', () => {
expect(result).toEqual({ a: 2, b: 3 })
})
})

describe('pick', () => {
it('should pick specified string keys from an object', () => {
const obj = { a: 1, b: 2, c: 3 }
const result = pick(obj, ['a', 'c'])

Check failure on line 351 in tests/collection.spec.ts

View workflow job for this annotation

GitHub Actions / test

tests/collection.spec.ts > pick > should pick specified string keys from an object

TypeError: pick is not a function ❯ tests/collection.spec.ts:351:20
expect(result).toEqual({ a: 1, c: 3 })
})

it('should pick specified symbol keys from an object', () => {
const symA = Symbol('a')
const symB = Symbol('b')
const obj = {
[symA]: 'valueA',
[symB]: 'valueB',
c: 3,
}

const result = pick(obj, [symA])

Check failure on line 364 in tests/collection.spec.ts

View workflow job for this annotation

GitHub Actions / test

tests/collection.spec.ts > pick > should pick specified symbol keys from an object

TypeError: pick is not a function ❯ tests/collection.spec.ts:364:20
expect(result).toEqual({
[symA]: 'valueA',
})
})

it('should pick elements by index from an array', () => {
const arr = [10, 20, 30, 40, 50]
const result = pick(arr, [0, 2, 4])

Check failure on line 372 in tests/collection.spec.ts

View workflow job for this annotation

GitHub Actions / test

tests/collection.spec.ts > pick > should pick elements by index from an array

TypeError: pick is not a function ❯ tests/collection.spec.ts:372:20
expect(result).toEqual({
'0': 10,
'2': 30,
'4': 50,
})
})
})

describe('omit', () => {
it('should omit specified string keys from an object', () => {
const obj = { a: 1, b: 2, c: 3 }
const result = omit(obj, ['b'])

Check failure on line 384 in tests/collection.spec.ts

View workflow job for this annotation

GitHub Actions / test

tests/collection.spec.ts > omit > should omit specified string keys from an object

TypeError: omit is not a function ❯ tests/collection.spec.ts:384:20
expect(result).toEqual({ a: 1, c: 3 })
})

it('should omit specified symbol keys from an object', () => {
const symA = Symbol('a')
const symB = Symbol('b')
const obj = {
[symA]: 'valueA',
[symB]: 'valueB',
c: 3,
}

const result = omit(obj, [symA])

Check failure on line 397 in tests/collection.spec.ts

View workflow job for this annotation

GitHub Actions / test

tests/collection.spec.ts > omit > should omit specified symbol keys from an object

TypeError: omit is not a function ❯ tests/collection.spec.ts:397:20
expect(result).toEqual({
[symB]: 'valueB',
c: 3,
})
})

it('should omit elements by index from an array', () => {
const arr = [10, 20, 30, 40, 50]
const result = omit(arr, [1, 3])

Check failure on line 406 in tests/collection.spec.ts

View workflow job for this annotation

GitHub Actions / test

tests/collection.spec.ts > omit > should omit elements by index from an array

TypeError: omit is not a function ❯ tests/collection.spec.ts:406:20
expect(result).toEqual([10, 30, 50])
})
})

describe('pickBy', () => {
it('should pick properties from an object based on the predicate for string keys', () => {
const obj = { a: 1, b: 2, c: 3 }
const result = pickBy(obj, (value) => value % 2 === 1)

Check failure on line 414 in tests/collection.spec.ts

View workflow job for this annotation

GitHub Actions / test

tests/collection.spec.ts > pickBy > should pick properties from an object based on the predicate for string keys

TypeError: pickBy is not a function ❯ tests/collection.spec.ts:414:20
expect(result).toEqual({ a: 1, c: 3 })
})

it('should pick properties from an object based on the predicate for symbol keys', () => {
const symA = Symbol('a')
const symB = Symbol('b')
const obj = {
[symA]: 1,
[symB]: 2,
c: 3,
}
const result = pickBy(obj, (value) => value === 2)

Check failure on line 426 in tests/collection.spec.ts

View workflow job for this annotation

GitHub Actions / test

tests/collection.spec.ts > pickBy > should pick properties from an object based on the predicate for symbol keys

TypeError: pickBy is not a function ❯ tests/collection.spec.ts:426:20
expect(result).toEqual({ [symB]: 2 })
})

it('should pick elements from an array based on the predicate', () => {
const arr: number[] = [10, 15, 20, 25, 30] // Explicitly specify the array as number[]
const result = pickBy(arr, (value) => value > 15)

Check failure on line 432 in tests/collection.spec.ts

View workflow job for this annotation

GitHub Actions / test

tests/collection.spec.ts > pickBy > should pick elements from an array based on the predicate

TypeError: pickBy is not a function ❯ tests/collection.spec.ts:432:20
expect(result).toEqual([20, 25, 30])
})
})

describe('omitBy', () => {
it('should omit properties from an object based on the predicate for string keys', () => {
const obj = { a: 1, b: 2, c: 3 }
const result = omitBy(obj, (value) => value % 2 === 1)

Check failure on line 440 in tests/collection.spec.ts

View workflow job for this annotation

GitHub Actions / test

tests/collection.spec.ts > omitBy > should omit properties from an object based on the predicate for string keys

TypeError: omitBy is not a function ❯ tests/collection.spec.ts:440:20
expect(result).toEqual({ b: 2 })
})

it('should omit properties from an object based on the predicate for symbol keys', () => {
const symA = Symbol('a')
const symB = Symbol('b')
const obj = {
[symA]: 1,
[symB]: 2,
c: 3,
}
const result = omitBy(obj, (value) => value === 2)
expect(result).toEqual({ [symA]: 1, c: 3 })
})

it('should omit elements from an array based on the predicate', () => {
const arr = [10, 15, 20, 25, 30]
const result = omitBy(arr, (value) => value < 20)
expect(result).toEqual([20, 25, 30])
})
})

0 comments on commit ee83029

Please sign in to comment.