From f475a131523b28a8028af0f8c8356054bc9b5830 Mon Sep 17 00:00:00 2001 From: Aybrea Date: Mon, 4 Nov 2024 21:43:48 +0800 Subject: [PATCH 1/2] chore: delete excessive exports --- src/index.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/index.ts b/src/index.ts index e2c0dfc..125e3c1 100644 --- a/src/index.ts +++ b/src/index.ts @@ -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' From ec14190c93af3deeda98fbd126a6f71c9266bc83 Mon Sep 17 00:00:00 2001 From: Aybrea Date: Thu, 7 Nov 2024 08:00:37 +0800 Subject: [PATCH 2/2] feat: add pick, omit, pickBy, and omitBy functions --- docs/collection/omit-by.md | 25 ++++++++ docs/collection/omit.md | 25 ++++++++ docs/collection/pick-by.md | 25 ++++++++ docs/collection/pick.md | 25 ++++++++ docs/zh/collection/omit-by.md | 25 ++++++++ docs/zh/collection/omit.md | 25 ++++++++ docs/zh/collection/pick-by.md | 25 ++++++++ docs/zh/collection/pick.md | 25 ++++++++ src/collection/omit-by.ts | 19 ++++++ src/collection/omit.ts | 15 +++++ src/collection/pick-by.ts | 12 ++++ src/collection/pick.ts | 9 +++ tests/collection.spec.ts | 117 +++++++++++++++++++++++++++++++++- 13 files changed, 371 insertions(+), 1 deletion(-) create mode 100644 docs/collection/omit-by.md create mode 100644 docs/collection/omit.md create mode 100644 docs/collection/pick-by.md create mode 100644 docs/collection/pick.md create mode 100644 docs/zh/collection/omit-by.md create mode 100644 docs/zh/collection/omit.md create mode 100644 docs/zh/collection/pick-by.md create mode 100644 docs/zh/collection/pick.md create mode 100644 src/collection/omit-by.ts create mode 100644 src/collection/omit.ts create mode 100644 src/collection/pick-by.ts create mode 100644 src/collection/pick.ts diff --git a/docs/collection/omit-by.md b/docs/collection/omit-by.md new file mode 100644 index 0000000..4a1cb79 --- /dev/null +++ b/docs/collection/omit-by.md @@ -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` | diff --git a/docs/collection/omit.md b/docs/collection/omit.md new file mode 100644 index 0000000..e8c8d76 --- /dev/null +++ b/docs/collection/omit.md @@ -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` | diff --git a/docs/collection/pick-by.md b/docs/collection/pick-by.md new file mode 100644 index 0000000..be32757 --- /dev/null +++ b/docs/collection/pick-by.md @@ -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` | diff --git a/docs/collection/pick.md b/docs/collection/pick.md new file mode 100644 index 0000000..db9dc06 --- /dev/null +++ b/docs/collection/pick.md @@ -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` | diff --git a/docs/zh/collection/omit-by.md b/docs/zh/collection/omit-by.md new file mode 100644 index 0000000..1729acc --- /dev/null +++ b/docs/zh/collection/omit-by.md @@ -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` | diff --git a/docs/zh/collection/omit.md b/docs/zh/collection/omit.md new file mode 100644 index 0000000..26d0cac --- /dev/null +++ b/docs/zh/collection/omit.md @@ -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` | diff --git a/docs/zh/collection/pick-by.md b/docs/zh/collection/pick-by.md new file mode 100644 index 0000000..a6bd2ca --- /dev/null +++ b/docs/zh/collection/pick-by.md @@ -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` | diff --git a/docs/zh/collection/pick.md b/docs/zh/collection/pick.md new file mode 100644 index 0000000..4e862ae --- /dev/null +++ b/docs/zh/collection/pick.md @@ -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` | diff --git a/src/collection/omit-by.ts b/src/collection/omit-by.ts new file mode 100644 index 0000000..84a339e --- /dev/null +++ b/src/collection/omit-by.ts @@ -0,0 +1,19 @@ +export function omitBy( + collection: T, + fn: (value: T extends any[] ? T[number] : T[keyof T], key: number | keyof T) => boolean, +): Partial | 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)[key] = value + } + return result + }, {} as Partial) + } +} diff --git a/src/collection/omit.ts b/src/collection/omit.ts new file mode 100644 index 0000000..b988137 --- /dev/null +++ b/src/collection/omit.ts @@ -0,0 +1,15 @@ +export function omit(object: T, keys: K[]): Omit { + const keysToOmit = new Set(keys) + const result = {} as Omit + 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 +} diff --git a/src/collection/pick-by.ts b/src/collection/pick-by.ts new file mode 100644 index 0000000..e2f8082 --- /dev/null +++ b/src/collection/pick-by.ts @@ -0,0 +1,12 @@ +export function pickBy(collection: T, fn: (value: any, key: keyof T) => boolean): Partial | 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)[key] = value + } + return result + }, {} as Partial) + } +} diff --git a/src/collection/pick.ts b/src/collection/pick.ts new file mode 100644 index 0000000..9546909 --- /dev/null +++ b/src/collection/pick.ts @@ -0,0 +1,9 @@ +export function pick(object: T, keys: K[]): Pick { + return keys.reduce( + (result, key) => { + result[key] = object[key] + return result + }, + {} as Pick, + ) +} diff --git a/tests/collection.spec.ts b/tests/collection.spec.ts index 0f5c15e..cf09aa4 100644 --- a/tests/collection.spec.ts +++ b/tests/collection.spec.ts @@ -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 }) @@ -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']) + 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]) + 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]) + 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']) + 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]) + 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]) + 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) + 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) + 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) + 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) + 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]) + }) +})