UNPKG

@cloudcome/utils-core

Version:
1 lines 11.1 kB
{"version":3,"file":"array.mjs","sources":["../src/array.ts"],"sourcesContent":["import { isArray, isObject } from './type';\nimport type { MaybePromise } from './types';\n\n/**\n * 检查给定的值是否为类数组对象。\n *\n * 类数组对象是指具有 `length` 属性且 `length` 属性为非负数的对象。\n *\n * @param unknown - 要检查的值。\n * @returns 如果值是类数组对象,则返回 `true`,否则返回 `false`。\n */\nexport function isArrayLike(unknown: unknown) {\n if (isArray(unknown)) return true;\n\n if (isObject(unknown)) {\n const arrayLike = unknown as { length: unknown };\n return typeof arrayLike.length === 'number' && arrayLike.length >= 0;\n }\n\n return false;\n}\n\n/**\n * 从数组中选择指定索引的元素。\n *\n * @param array - 要从中选择元素的数组。\n * @param indexes - 要选择的元素的索引数组。\n * @returns 包含指定索引元素的新数组。\n */\nexport function arrayPick<T>(array: T[], indexes: number[]) {\n const indexes2 = [...indexes];\n return array.filter((_, i) => {\n const index = indexes2.indexOf(i);\n if (index === -1) return false;\n indexes2.splice(index, 1);\n return true;\n });\n}\n\n/**\n * 从数组中排除指定索引的元素。\n *\n * @param array - 要从中排除元素的数组。\n * @param indexes - 要排除的元素的索引数组。\n * @returns 包含排除指定索引元素后的新数组。\n */\nexport function arrayOmit<T>(array: T[], indexes: number[]) {\n const indexes2 = [...indexes];\n return array.filter((_, i) => {\n const index = indexes2.indexOf(i);\n if (index === -1) return true;\n indexes2.splice(index, 1);\n return false;\n });\n}\n\n/**\n * 遍历数组中的每个元素,并对每个元素执行提供的回调函数。\n *\n * @param array - 要遍历的数组。\n * @param iterator - 对每个元素执行的回调函数。如果回调函数返回 `false`,则提前终止遍历。\n * @param reverse - 是否以相反的顺序遍历数组。默认为 `false`。\n * @returns 无返回值。\n *\n * @example\n * ```typescript\n * const arr = [1, 2, 3];\n * arrayEach(arr, (item, index) => {\n * console.log(item, index);\n * if (index === 1) return false; // 提前终止遍历\n * });\n * ```\n */\nexport function arrayEach<T>(array: T[], iterator: (item: T, index: number) => false | unknown, reverse = false) {\n const _array = [...array];\n const length = array.length;\n\n if (reverse) {\n for (let i = length - 1; i >= 0; i--) {\n if (iterator(_array[i], i) === false) {\n break;\n }\n }\n } else {\n for (let i = 0; i < length; i++) {\n if (iterator(_array[i], i) === false) {\n break;\n }\n }\n }\n}\n\n/**\n * 异步遍历数组中的每个元素,并对每个元素执行提供的回调函数。\n *\n * @param array - 要遍历的数组。\n * @param iterator - 对每个元素执行的异步回调函数。如果回调函数返回 `false`,则提前终止遍历。\n * @param reverse - 是否以相反的顺序遍历数组。默认为 `false`。\n * @returns 无返回值。\n *\n * @example\n * ```typescript\n * const arr = [1, 2, 3];\n * await arrayEachAsync(arr, async (item, index) => {\n * await someAsyncOperation(item);\n * if (index === 1) return false; // 提前终止遍历\n * });\n * ```\n */\nexport async function arrayEachAsync<T>(\n array: T[],\n iterator: (item: T, index: number) => MaybePromise<false | unknown>,\n reverse = false,\n) {\n const _array = [...array];\n const length = array.length;\n\n if (reverse) {\n for (let i = length - 1; i >= 0; i--) {\n if ((await iterator(_array[i], i)) === false) {\n break;\n }\n }\n } else {\n for (let i = 0; i < length; i++) {\n if ((await iterator(_array[i], i)) === false) {\n break;\n }\n }\n }\n}\n\n/**\n * 将数组中的元素移动到指定位置。\n *\n * @param array - 要移动元素的数组。\n * @param from - 要移动的元素的起始位置。\n * @param to - 要移动的元素的目标位置。\n * @returns 新的数组,其中包含移动后的元素。\n *\n * @example\n * ```typescript\n * const arr = [1, 2, 3, 4, 5];\n * const newArr = arrayMove(arr, 1, 3);\n * // 返回 [1, 3, 4, 2, 5]\n * ```\n */\nexport function arrayMove<T>(array: T[], from: number, to: number) {\n const array2 = [...array];\n\n if (from < 0 || from >= array2.length || to < 0 || to >= array2.length) {\n return array2;\n }\n\n const item = array2[from];\n\n array2.splice(from, 1);\n array2.splice(to, 0, item);\n\n return array2;\n}\n\n/**\n * 比较两个数组的差异,返回包含删除、新增和相同元素信息的对象\n *\n * @template T - 数组元素的类型\n * @param {T[]} refArray - 参考数组(原始数组)\n * @param {T[]} curArray - 当前数组(比较数组)\n * @returns {ArrayDiffs<T>} 包含差异信息的对象\n *\n * @example\n * ```typescript\n * const ref = [1, 2, 3];\n * const cur = [2, 3, 4];\n * const diff = arrayDiff(ref, cur);\n * // 返回结果:\n * // {\n * // deletes: [{refIndexes: [0], refValue: 1}],\n * // adds: [{curIndexes: [2], curValue: 4}],\n * // equals: [\n * // {refIndexes: [1], curIndexes: [0], refValue: 2, curValue: 2},\n * // {refIndexes: [2], curIndexes: [1], refValue: 3, curValue: 3}\n * // ]\n * // }\n * ```\n */\nexport type ArrayDiffs<T> = {\n /**\n * 被删除的元素列表\n * @type {Array}\n * @property {number[]} refIndexes - 元素在参考数组中的所有索引位置\n * @property {T} refValue - 被删除的元素值\n */\n deletes: {\n /**\n * 元素在参考数组中的所有索引位置\n * @type {number[]}\n */\n refIndexes: number[];\n /**\n * 被删除的元素值\n * @type {T}\n */\n refValue: T;\n }[];\n\n /**\n * 新增的元素列表\n * @type {Array}\n * @property {number[]} curIndexes - 元素在当前数组中的所有索引位置\n * @property {T} curValue - 新增的元素值\n */\n adds: {\n /**\n * 元素在当前数组中的所有索引位置\n * @type {number[]}\n */\n curIndexes: number[];\n /**\n * 新增的元素值\n * @type {T}\n */\n curValue: T;\n }[];\n\n /**\n * 相同的元素列表\n * @type {Array}\n * @property {number[]} refIndexes - 元素在参考数组中的所有索引位置\n * @property {number[]} curIndexes - 元素在当前数组中的所有索引位置\n * @property {T} refValue - 参考数组中的元素值\n * @property {T} curValue - 当前数组中的元素值\n */\n equals: {\n /**\n * 元素在参考数组中的所有索引位置\n * @type {number[]}\n */\n refIndexes: number[];\n /**\n * 元素在当前数组中的所有索引位置\n * @type {number[]}\n */\n curIndexes: number[];\n /**\n * 参考数组中的元素值\n * @type {T}\n */\n refValue: T;\n /**\n * 当前数组中的元素值\n * @type {T}\n */\n curValue: T;\n }[];\n};\n\nexport function arrayDiff<T>(refArray: T[], curArray: T[]): ArrayDiffs<T> {\n const buildMap = (arr: T[]) => {\n const map = new Map<T, number[]>();\n\n arr.forEach((item, index) => {\n const indexes = map.get(item) || [];\n indexes.push(index);\n map.set(item, indexes);\n });\n\n return map;\n };\n const map1 = buildMap(refArray);\n const map2 = buildMap(curArray);\n const deletes = new Set<T>();\n const adds = new Set<T>();\n const equals = new Set<T>();\n\n for (const key of map1.keys()) {\n if (map2.has(key)) {\n equals.add(key);\n } else {\n deletes.add(key);\n }\n }\n\n for (const key of map2.keys()) {\n if (!map1.has(key)) {\n adds.add(key);\n }\n }\n\n return {\n deletes: [...deletes].map((it) => ({\n // biome-ignore lint/style/noNonNullAssertion: <explanation>\n refIndexes: map1.get(it)!,\n refValue: it,\n })),\n\n adds: [...adds].map((it) => ({\n // biome-ignore lint/style/noNonNullAssertion: <explanation>\n curIndexes: map2.get(it)!,\n curValue: it,\n })),\n\n equals: [...equals].map((it) => ({\n // biome-ignore lint/style/noNonNullAssertion: <explanation>\n refIndexes: map1.get(it)!,\n // biome-ignore lint/style/noNonNullAssertion: <explanation>\n curIndexes: map2.get(it)!,\n refValue: it,\n curValue: it,\n })),\n };\n}\n"],"names":[],"mappings":";AAWO,SAAS,YAAY,SAAkB;AACxC,MAAA,QAAQ,OAAO,EAAU,QAAA;AAEzB,MAAA,SAAS,OAAO,GAAG;AACrB,UAAM,YAAY;AAClB,WAAO,OAAO,UAAU,WAAW,YAAY,UAAU,UAAU;AAAA,EAAA;AAG9D,SAAA;AACT;AASgB,SAAA,UAAa,OAAY,SAAmB;AACpD,QAAA,WAAW,CAAC,GAAG,OAAO;AAC5B,SAAO,MAAM,OAAO,CAAC,GAAG,MAAM;AACtB,UAAA,QAAQ,SAAS,QAAQ,CAAC;AAC5B,QAAA,UAAU,GAAW,QAAA;AAChB,aAAA,OAAO,OAAO,CAAC;AACjB,WAAA;AAAA,EAAA,CACR;AACH;AASgB,SAAA,UAAa,OAAY,SAAmB;AACpD,QAAA,WAAW,CAAC,GAAG,OAAO;AAC5B,SAAO,MAAM,OAAO,CAAC,GAAG,MAAM;AACtB,UAAA,QAAQ,SAAS,QAAQ,CAAC;AAC5B,QAAA,UAAU,GAAW,QAAA;AAChB,aAAA,OAAO,OAAO,CAAC;AACjB,WAAA;AAAA,EAAA,CACR;AACH;AAmBO,SAAS,UAAa,OAAY,UAAuD,UAAU,OAAO;AACzG,QAAA,SAAS,CAAC,GAAG,KAAK;AACxB,QAAM,SAAS,MAAM;AAErB,MAAI,SAAS;AACX,aAAS,IAAI,SAAS,GAAG,KAAK,GAAG,KAAK;AACpC,UAAI,SAAS,OAAO,CAAC,GAAG,CAAC,MAAM,OAAO;AACpC;AAAA,MAAA;AAAA,IACF;AAAA,EACF,OACK;AACL,aAAS,IAAI,GAAG,IAAI,QAAQ,KAAK;AAC/B,UAAI,SAAS,OAAO,CAAC,GAAG,CAAC,MAAM,OAAO;AACpC;AAAA,MAAA;AAAA,IACF;AAAA,EACF;AAEJ;AAmBA,eAAsB,eACpB,OACA,UACA,UAAU,OACV;AACM,QAAA,SAAS,CAAC,GAAG,KAAK;AACxB,QAAM,SAAS,MAAM;AAErB,MAAI,SAAS;AACX,aAAS,IAAI,SAAS,GAAG,KAAK,GAAG,KAAK;AACpC,UAAK,MAAM,SAAS,OAAO,CAAC,GAAG,CAAC,MAAO,OAAO;AAC5C;AAAA,MAAA;AAAA,IACF;AAAA,EACF,OACK;AACL,aAAS,IAAI,GAAG,IAAI,QAAQ,KAAK;AAC/B,UAAK,MAAM,SAAS,OAAO,CAAC,GAAG,CAAC,MAAO,OAAO;AAC5C;AAAA,MAAA;AAAA,IACF;AAAA,EACF;AAEJ;AAiBgB,SAAA,UAAa,OAAY,MAAc,IAAY;AAC3D,QAAA,SAAS,CAAC,GAAG,KAAK;AAEpB,MAAA,OAAO,KAAK,QAAQ,OAAO,UAAU,KAAK,KAAK,MAAM,OAAO,QAAQ;AAC/D,WAAA;AAAA,EAAA;AAGH,QAAA,OAAO,OAAO,IAAI;AAEjB,SAAA,OAAO,MAAM,CAAC;AACd,SAAA,OAAO,IAAI,GAAG,IAAI;AAElB,SAAA;AACT;AAiGgB,SAAA,UAAa,UAAe,UAA8B;AAClE,QAAA,WAAW,CAAC,QAAa;AACvB,UAAA,0BAAU,IAAiB;AAE7B,QAAA,QAAQ,CAAC,MAAM,UAAU;AAC3B,YAAM,UAAU,IAAI,IAAI,IAAI,KAAK,CAAC;AAClC,cAAQ,KAAK,KAAK;AACd,UAAA,IAAI,MAAM,OAAO;AAAA,IAAA,CACtB;AAEM,WAAA;AAAA,EACT;AACM,QAAA,OAAO,SAAS,QAAQ;AACxB,QAAA,OAAO,SAAS,QAAQ;AACxB,QAAA,8BAAc,IAAO;AACrB,QAAA,2BAAW,IAAO;AAClB,QAAA,6BAAa,IAAO;AAEf,aAAA,OAAO,KAAK,QAAQ;AACzB,QAAA,KAAK,IAAI,GAAG,GAAG;AACjB,aAAO,IAAI,GAAG;AAAA,IAAA,OACT;AACL,cAAQ,IAAI,GAAG;AAAA,IAAA;AAAA,EACjB;AAGS,aAAA,OAAO,KAAK,QAAQ;AAC7B,QAAI,CAAC,KAAK,IAAI,GAAG,GAAG;AAClB,WAAK,IAAI,GAAG;AAAA,IAAA;AAAA,EACd;AAGK,SAAA;AAAA,IACL,SAAS,CAAC,GAAG,OAAO,EAAE,IAAI,CAAC,QAAQ;AAAA;AAAA,MAEjC,YAAY,KAAK,IAAI,EAAE;AAAA,MACvB,UAAU;AAAA,IAAA,EACV;AAAA,IAEF,MAAM,CAAC,GAAG,IAAI,EAAE,IAAI,CAAC,QAAQ;AAAA;AAAA,MAE3B,YAAY,KAAK,IAAI,EAAE;AAAA,MACvB,UAAU;AAAA,IAAA,EACV;AAAA,IAEF,QAAQ,CAAC,GAAG,MAAM,EAAE,IAAI,CAAC,QAAQ;AAAA;AAAA,MAE/B,YAAY,KAAK,IAAI,EAAE;AAAA;AAAA,MAEvB,YAAY,KAAK,IAAI,EAAE;AAAA,MACvB,UAAU;AAAA,MACV,UAAU;AAAA,IAAA,EACV;AAAA,EACJ;AACF;"}