diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts index 572b3b6..fdeea28 100644 --- a/docs/.vitepress/config.ts +++ b/docs/.vitepress/config.ts @@ -4,6 +4,7 @@ import { numberItems, stringItems, arrayItems, + objectItems, functionItems, collectionItems, mathItems, @@ -57,6 +58,10 @@ export default defineConfig({ text: '数学', items: withI18n(mathItems, 'zh'), }, + { + text: '对象', + items: withI18n(objectItems, 'zh'), + }, { text: '数组', items: withI18n(arrayItems, 'zh'), @@ -119,6 +124,10 @@ export default defineConfig({ text: 'Math', items: mathItems, }, + { + text: 'Object', + items: objectItems, + }, { text: 'Array', items: arrayItems, diff --git a/docs/.vitepress/items/index.ts b/docs/.vitepress/items/index.ts index 6266897..68b311c 100644 --- a/docs/.vitepress/items/index.ts +++ b/docs/.vitepress/items/index.ts @@ -1,6 +1,7 @@ export * from './general' export * from './string' export * from './number' +export * from './object' export * from './array' export * from './collection' export * from './function' diff --git a/docs/.vitepress/items/object.ts b/docs/.vitepress/items/object.ts new file mode 100644 index 0000000..cdc0dd5 --- /dev/null +++ b/docs/.vitepress/items/object.ts @@ -0,0 +1,6 @@ +export const objectItems = [ + { text: 'pick', link: '/object/pick' }, + { text: 'pickBy', link: '/object/pick-by' }, + { text: 'omit', link: '/object/omit' }, + { text: 'omitBy', link: '/object/omit-by' }, +] diff --git a/docs/array/uniq-by.md b/docs/array/uniq-by.md index e68a5be..e3ebe03 100644 --- a/docs/array/uniq-by.md +++ b/docs/array/uniq-by.md @@ -13,10 +13,10 @@ uniqBy([{ id: 1 }, { id: 2 }, { id: 1 }], (a, b) => a.id === b.id) ### Arguments -| Arg | Type | Defaults | -| ----- | ----------------------------- | -------- | -| `arr` | `Array` | | -| `fn` | `(a: any, b: any) => boolean` | | +| Arg | Type | Defaults | +| ----- | ------------------------- | -------- | +| `arr` | `Array` | | +| `fn` | `(a: any, b: any) => any` | | ### Return diff --git a/docs/collection/omit-by.md b/docs/collection/omit-by.md deleted file mode 100644 index 4a1cb79..0000000 --- a/docs/collection/omit-by.md +++ /dev/null @@ -1,25 +0,0 @@ -# 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/pick-by.md b/docs/collection/pick-by.md deleted file mode 100644 index be32757..0000000 --- a/docs/collection/pick-by.md +++ /dev/null @@ -1,25 +0,0 @@ -# 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/object/omit-by.md b/docs/object/omit-by.md new file mode 100644 index 0000000..d3c3995 --- /dev/null +++ b/docs/object/omit-by.md @@ -0,0 +1,27 @@ +# omitBy + +Excludes an object property by providing a function that constructs a new object. Returns a `truthy` value to indicate that the property should be excluded. + +### Usage + +```ts +import { omitBy } from 'rattail' + +omitBy({ a: 1, b: 2, c: 3 }, (value) => value > 1) +// return { a: 1 } +omitBy({ a: 1, b: 2, c: 3 }, (value, key) => key !== 'a') +// return { a: 1 } +``` + +### Arguments + +| Arg | Type | Defaults | +| -------- | ---------------------------------- | -------- | +| `object` | `object` | | +| `fn` | `(value: any, key: string) => any` | | + +### Return + +| Type | +| -------- | +| `object` | diff --git a/docs/collection/omit.md b/docs/object/omit.md similarity index 82% rename from docs/collection/omit.md rename to docs/object/omit.md index e8c8d76..3e2ba8e 100644 --- a/docs/collection/omit.md +++ b/docs/object/omit.md @@ -1,6 +1,6 @@ # omit -Creates a new object by omitting specified keys from an existing object. +Excludes object properties and constructs a new object. ### Usage diff --git a/docs/object/pick-by.md b/docs/object/pick-by.md new file mode 100644 index 0000000..b0f27f9 --- /dev/null +++ b/docs/object/pick-by.md @@ -0,0 +1,27 @@ +# pickBy + +By providing a function to extract object properties and construct a new object, returning a `truthy` value indicates that the property needs to be extracted. + +### Usage + +```ts +import { pickBy } from 'rattail' + +pickBy({ a: 1, b: 2, c: 3 }, (value) => value > 1) +// return { b: 2, c: 3 } +pickBy({ a: 1, b: 2, c: 3 }, (value, key) => key !== 'a') +// return { b: 2, c: 3 } +``` + +### Arguments + +| Arg | Type | Defaults | +| -------- | ---------------------------------- | -------- | +| `object` | `object` | | +| `fn` | `(value: any, key: string) => any` | | + +### Return + +| Type | +| -------- | +| `object` | diff --git a/docs/collection/pick.md b/docs/object/pick.md similarity index 82% rename from docs/collection/pick.md rename to docs/object/pick.md index db9dc06..e0e02d1 100644 --- a/docs/collection/pick.md +++ b/docs/object/pick.md @@ -1,6 +1,6 @@ # pick -Creates a new object by selecting specified keys from an existing object. +Pick object properties and construct a new object. ### Usage diff --git a/docs/zh/array/uniq-by.md b/docs/zh/array/uniq-by.md index e215ada..56913a7 100644 --- a/docs/zh/array/uniq-by.md +++ b/docs/zh/array/uniq-by.md @@ -13,10 +13,10 @@ uniqBy([{ id: 1 }, { id: 2 }, { id: 1 }], (a, b) => a.id === b.id) ### 参数 -| 参数 | 类型 | 默认值 | -| ----- | ----------------------------- | ------ | -| `arr` | `Array` | | -| `fn` | `(a: any, b: any) => boolean` | | +| 参数 | 类型 | 默认值 | +| ----- | ------------------------- | ------ | +| `arr` | `Array` | | +| `fn` | `(a: any, b: any) => any` | | ### 返回值 diff --git a/docs/zh/collection/omit-by.md b/docs/zh/collection/omit-by.md deleted file mode 100644 index 1729acc..0000000 --- a/docs/zh/collection/omit-by.md +++ /dev/null @@ -1,25 +0,0 @@ -# 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/pick-by.md b/docs/zh/collection/pick-by.md deleted file mode 100644 index a6bd2ca..0000000 --- a/docs/zh/collection/pick-by.md +++ /dev/null @@ -1,25 +0,0 @@ -# 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/math/max-by.md b/docs/zh/math/max-by.md index 7232954..7b5dabb 100644 --- a/docs/zh/math/max-by.md +++ b/docs/zh/math/max-by.md @@ -20,6 +20,6 @@ maxBy([{ n: 5 }, { n: 10 }, { n: 8 }], ({ n }) => n) ### 返回值 -| 类型 | -| :--: | ---------- | -| `T | undefined` | +| 类型 | +| :---------------: | +| `T \| undefined` | diff --git a/docs/zh/object/omit-by.md b/docs/zh/object/omit-by.md new file mode 100644 index 0000000..ddf9ea7 --- /dev/null +++ b/docs/zh/object/omit-by.md @@ -0,0 +1,27 @@ +# omitBy + +通过提供一个函数来排除对象属性并构造成一个新的对象, 返回 `真值` 表示需要排除该属性。 + +### 使用 + +```ts +import { omitBy } from 'rattail' + +omitBy({ a: 1, b: 2, c: 3 }, (value) => value > 1) +// return { a: 1 } +omitBy({ a: 1, b: 2, c: 3 }, (value, key) => key !== 'a') +// return { a: 1 } +``` + +### 参数 + +| 参数 | 类型 | 默认值 | +| -------- | ---------------------------------- | ------ | +| `object` | `object` | | +| `fn` | `(value: any, key: string) => any` | | + +### 返回值 + +| 类型 | +| -------- | +| `object` | diff --git a/docs/zh/collection/omit.md b/docs/zh/object/omit.md similarity index 84% rename from docs/zh/collection/omit.md rename to docs/zh/object/omit.md index 26d0cac..c99f52c 100644 --- a/docs/zh/collection/omit.md +++ b/docs/zh/object/omit.md @@ -1,6 +1,6 @@ # omit -通过从现有对象中排除指定键来创建新对象。 +排除对象属性并构造成一个新的对象。 ### 使用 diff --git a/docs/zh/object/pick-by.md b/docs/zh/object/pick-by.md new file mode 100644 index 0000000..7f8e068 --- /dev/null +++ b/docs/zh/object/pick-by.md @@ -0,0 +1,27 @@ +# pickBy + +通过提供一个函数来提取对象属性并构造成一个新的对象, 返回 `真值` 表示需要提取该属性。 + +### 使用 + +```ts +import { pickBy } from 'rattail' + +pickBy({ a: 1, b: 2, c: 3 }, (value) => value > 1) +// return { b: 2, c: 3 } +pickBy({ a: 1, b: 2, c: 3 }, (value, key) => key !== 'a') +// return { b: 2, c: 3 } +``` + +### 参数 + +| 参数 | 类型 | 默认值 | +| -------- | ---------------------------------- | ------ | +| `object` | `object` | | +| `fn` | `(value: any, key: string) => any` | | + +### 返回值 + +| 类型 | +| -------- | +| `object` | diff --git a/docs/zh/collection/pick.md b/docs/zh/object/pick.md similarity index 84% rename from docs/zh/collection/pick.md rename to docs/zh/object/pick.md index 4e862ae..82ad3ad 100644 --- a/docs/zh/collection/pick.md +++ b/docs/zh/object/pick.md @@ -1,6 +1,6 @@ # pick -通过从现有对象中选择指定键来创建新对象。 +提取对象属性并构造成一个新的对象。 ### 使用 diff --git a/src/array/uniqBy.ts b/src/array/uniqBy.ts index bd265f4..84c858f 100644 --- a/src/array/uniqBy.ts +++ b/src/array/uniqBy.ts @@ -1,4 +1,4 @@ -export function uniqBy(arr: T[], fn: (a: T, b: T) => boolean): T[] { +export function uniqBy(arr: T[], fn: (a: T, b: T) => any): T[] { return arr.reduce((ret: T[], i: T) => { const index = ret.findIndex((j: T) => fn(i, j)) diff --git a/src/collection/omit-by.ts b/src/collection/omit-by.ts deleted file mode 100644 index 84a339e..0000000 --- a/src/collection/omit-by.ts +++ /dev/null @@ -1,19 +0,0 @@ -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 deleted file mode 100644 index b988137..0000000 --- a/src/collection/omit.ts +++ /dev/null @@ -1,15 +0,0 @@ -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 deleted file mode 100644 index e2f8082..0000000 --- a/src/collection/pick-by.ts +++ /dev/null @@ -1,12 +0,0 @@ -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/index.ts b/src/index.ts index 125e3c1..b6b9c9e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,4 +1,5 @@ export * from './array' +export * from './object' export * from './util' export * from './function' export * from './general' diff --git a/src/object/index.ts b/src/object/index.ts new file mode 100644 index 0000000..0359cde --- /dev/null +++ b/src/object/index.ts @@ -0,0 +1,4 @@ +export * from './pick' +export * from './pickBy' +export * from './omit' +export * from './omitBy' diff --git a/src/object/omit.ts b/src/object/omit.ts new file mode 100644 index 0000000..712203b --- /dev/null +++ b/src/object/omit.ts @@ -0,0 +1,14 @@ +export function omit(object: T, keys: K[]): Omit { + const ownKeys = [...Object.keys(object), ...Object.getOwnPropertySymbols(object)] + + return ownKeys.reduce( + (result, key) => { + if (!keys.includes(key as K)) { + result[key as keyof typeof result] = object[key as keyof typeof result] + } + + return result + }, + {} as Omit, + ) +} diff --git a/src/object/omitBy.ts b/src/object/omitBy.ts new file mode 100644 index 0000000..257e0cf --- /dev/null +++ b/src/object/omitBy.ts @@ -0,0 +1,13 @@ +export function omitBy(object: T, fn: (value: any, key: keyof T) => any): Partial { + const ownKeys = [...Object.keys(object), ...Object.getOwnPropertySymbols(object)] + + return ownKeys.reduce((result, key) => { + const value = object[key as keyof typeof object] + + if (!fn(value, key as keyof T)) { + result[key as keyof typeof result] = value + } + + return result + }, {} as Partial) +} diff --git a/src/collection/pick.ts b/src/object/pick.ts similarity index 100% rename from src/collection/pick.ts rename to src/object/pick.ts diff --git a/src/object/pickBy.ts b/src/object/pickBy.ts new file mode 100644 index 0000000..5e3bd3e --- /dev/null +++ b/src/object/pickBy.ts @@ -0,0 +1,13 @@ +export function pickBy(object: T, fn: (value: any, key: keyof T) => any): Partial { + const ownKeys = [...Object.keys(object), ...Object.getOwnPropertySymbols(object)] + + return ownKeys.reduce((result, key) => { + const value = object[key as keyof typeof object] + + if (fn(value, key as keyof T)) { + result[key as keyof typeof result] = value + } + + return result + }, {} as Partial) +} diff --git a/tests/collection.spec.ts b/tests/collection.spec.ts index cf09aa4..0f5c15e 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, pick, omit, pickBy, omitBy } from '../src' +import { merge, mergeWith, cloneDeep, cloneDeepWith, isNumber, hasOwn } from '../src' it('should merge two objects', () => { const result = merge({ a: 1, b: { c: 2 } }, { b: { d: 3 }, e: 4 }) @@ -344,118 +344,3 @@ 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]) - }) -}) diff --git a/tests/object.spec.ts b/tests/object.spec.ts new file mode 100644 index 0000000..87ba667 --- /dev/null +++ b/tests/object.spec.ts @@ -0,0 +1,74 @@ +import { describe, expect, it } from 'vitest' +import { omit, omitBy, pick, pickBy } from '../src' + +describe('pick', () => { + it('should pick specified string keys from an object', () => { + const result = pick({ a: 1, b: 2, c: 3 }, ['a', 'c']) + expect(result).toEqual({ a: 1, c: 3 }) + }) + + it('should pick specified symbol keys from an object', () => { + const a = Symbol('a') + + const result = pick( + { + [a]: 1, + b: 3, + }, + [a], + ) + + expect(result).toEqual({ + [a]: 1, + }) + }) +}) + +it('pickBy', () => { + expect(pickBy({ a: 1, b: 2, c: 3 }, (value) => value === 2)).toEqual({ b: 2 }) + expect(pickBy({ a: 1, b: 2, c: 3 }, (value) => value > 1)).toEqual({ b: 2, c: 3 }) + expect(pickBy({ a: 1, b: 2, c: 3 }, (value, key) => key !== 'a')).toEqual({ b: 2, c: 3 }) + + const a = Symbol('a') + expect( + pickBy( + { + [a]: 1, + b: 2, + }, + (value, key) => key === a, + ), + ).toEqual({ [a]: 1 }) +}) + +it('omit', () => { + expect(omit({ a: 1, b: 2, c: 3 }, ['a', 'c'])).toEqual({ b: 2 }) + const a = Symbol('a') + + expect( + omit( + { + [a]: 1, + b: 2, + }, + [a], + ), + ).toEqual({ + b: 2, + }) +}) + +it('omitBy', () => { + expect(omitBy({ a: 1, b: 2, c: 3 }, (value) => value > 1)).toEqual({ a: 1 }) + expect(omitBy({ a: 1, b: 2, c: 3 }, (value, key) => key !== 'a')).toEqual({ a: 1 }) + + const a = Symbol('a') + const result = omitBy( + { + [a]: 1, + b: 2, + }, + (value, key) => key === a, + ) + expect(result).toEqual({ b: 2 }) +})