From 11198214d3c4c42e1e760463079c54803151c285 Mon Sep 17 00:00:00 2001 From: akino <1947055799@qq.com> Date: Wed, 30 Nov 2022 07:59:34 +0800 Subject: [PATCH] feat(array): `isDeepEqual` and `uniqueBy` (#24) Co-authored-by: Anthony Fu --- src/array.ts | 14 ++++++++++++++ src/base.ts | 6 ++++++ src/equal.ts | 27 +++++++++++++++++++++++++++ 3 files changed, 47 insertions(+) create mode 100644 src/equal.ts diff --git a/src/array.ts b/src/array.ts index 173bfc8..644bc97 100644 --- a/src/array.ts +++ b/src/array.ts @@ -69,6 +69,20 @@ export function uniq(array: readonly T[]): T[] { return Array.from(new Set(array)) } +/** + * Unique an Array by a custom equality function + * + * @category Array + */ +export function uniqueBy(array: readonly T[], equalFn: (a: any, b: any) => boolean): T[] { + return array.reduce((acc: T[], cur: any) => { + const index = acc.findIndex((item: any) => equalFn(cur, item)) + if (index === -1) + acc.push(cur) + return acc + }, []) +} + /** * Get last item * diff --git a/src/base.ts b/src/base.ts index 04ab0e5..03e5656 100644 --- a/src/base.ts +++ b/src/base.ts @@ -3,4 +3,10 @@ export const assert = (condition: boolean, message: string): asserts condition = throw new Error(message) } export const toString = (v: any) => Object.prototype.toString.call(v) +export const getTypeName = (v: any) => { + if (v === null) + return 'null' + const type = toString(v).slice(8, -1).toLowerCase() + return typeof v === 'object' || typeof v === 'function' ? type : typeof v +} export const noop = () => {} diff --git a/src/equal.ts b/src/equal.ts new file mode 100644 index 0000000..93a4cbc --- /dev/null +++ b/src/equal.ts @@ -0,0 +1,27 @@ +import { getTypeName } from './base' + +export function isDeepEqual(value1: any, value2: any): boolean { + const type1 = getTypeName(value1) + const type2 = getTypeName(value2) + if (type1 !== type2) + return false + + if (type1 === 'array') { + if (value1.length !== value2.length) + return false + + return value1.every((item: any, i: number) => { + return isDeepEqual(item, value2[i]) + }) + } + if (type1 === 'object') { + const keyArr = Object.keys(value1) + if (keyArr.length !== Object.keys(value2).length) + return false + + return keyArr.every((key: string) => { + return isDeepEqual(value1[key], value2[key]) + }) + } + return value1 === value2 +}