638 lines
18 KiB
TypeScript
638 lines
18 KiB
TypeScript
import { _decorator } from "cc";
|
||
const { ccclass } = _decorator;
|
||
|
||
@ccclass("Lodash")
|
||
export class Lodash {
|
||
/* class member could be defined like this */
|
||
// dummy = '';
|
||
/**
|
||
* 遍历 collection(集合)元素,返回 predicate(断言函数)第一个返回真值的第一个元素
|
||
* @param {any} collection 一个用来迭代的集合
|
||
* @param {Function} predicate 每次迭代调用的函数。
|
||
* @returns 返回匹配元素,否则返回 undefined。
|
||
*/
|
||
public static find (collection: any, predicate: Function) {
|
||
var result;
|
||
if (!Array.isArray(collection)) {
|
||
collection = Lodash._toArray(collection);
|
||
}
|
||
|
||
result = collection.filter(predicate);
|
||
if (result.length) {
|
||
return result[0];
|
||
}
|
||
|
||
return undefined;
|
||
}
|
||
|
||
/**
|
||
* 调用 iteratee 遍历 collection(集合) 中的每个元素
|
||
* @param {any} collection 一个用来迭代的集合
|
||
* @param {Function} iteratee 每次迭代调用的函数。
|
||
*/
|
||
public static forEach(collection: any, iteratee: any) {
|
||
if (!Array.isArray(collection)) {
|
||
var array = Lodash._toArrayKey(collection);
|
||
array.forEach(function (value: any, index: number, arr: any[]) {
|
||
var key1 = value['key'];
|
||
var value1 = value['value'];
|
||
iteratee(value1, key1, collection);
|
||
});
|
||
} else {
|
||
collection.forEach(iteratee);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 深度拷贝
|
||
* @param {any} sObj 拷贝的对象
|
||
* @returns
|
||
*/
|
||
public static cloneDeep(sObj: any) {
|
||
if (sObj === null || typeof sObj !== "object") {
|
||
return sObj;
|
||
}
|
||
|
||
let s: any = {};
|
||
if (sObj.constructor === Array) {
|
||
s = [];
|
||
}
|
||
|
||
for (let i in sObj) {
|
||
if (sObj.hasOwnProperty(i)) {
|
||
s[i] = Lodash.cloneDeep(sObj[i]);
|
||
}
|
||
}
|
||
|
||
return s;
|
||
}
|
||
|
||
/**
|
||
* 创建一个数组, value(值) 是 iteratee(迭代函数)遍历 collection(集合)中的每个元素后返回的结果。
|
||
* @param {Array|Object} collection 一个用来迭代的集合.
|
||
* @param {Function} predicate 一个迭代函数,用来转换key(键
|
||
* @returns {Array} 返回一个组成集合数组
|
||
*/
|
||
public static map(collection: any, iteratee: any) {
|
||
if (!Array.isArray(collection)) {
|
||
collection = Lodash._toArray(collection);
|
||
}
|
||
|
||
let arr: any[] = [];
|
||
collection.forEach(function (value: any, index: number, array: []) {
|
||
arr.push(iteratee(value, index, array));
|
||
});
|
||
|
||
return arr;
|
||
}
|
||
|
||
/**
|
||
*
|
||
* @param srcObj
|
||
* @returns
|
||
*/
|
||
private static _toArrayKey(srcObj: { [x: string]: any; hasOwnProperty: (arg0: string) => any; }) {
|
||
var resultArr = [];
|
||
|
||
// to array
|
||
for (var key in srcObj) {
|
||
if (!srcObj.hasOwnProperty(key)) {
|
||
continue;
|
||
}
|
||
|
||
resultArr.push({ key: key, value: srcObj[key] });
|
||
}
|
||
|
||
return resultArr;
|
||
}
|
||
|
||
private static _toArray(srcObj: any) {
|
||
let resultArr: any[] = [];
|
||
|
||
// to array
|
||
for (var key in srcObj) {
|
||
if (!srcObj.hasOwnProperty(key)) {
|
||
continue;
|
||
}
|
||
|
||
resultArr.push(srcObj[key]);
|
||
}
|
||
|
||
return resultArr;
|
||
}
|
||
|
||
/**
|
||
* 遍历 collection(集合)元素,返回 predicate(断言函数)返回真值 的所有元素的数组。
|
||
* @param {Array|Object} collection 一个用来迭代的集合.
|
||
* @param {Function} predicate 一个迭代函数,用来转换key(键
|
||
* @returns 返回一个新的过滤后的数组。
|
||
*/
|
||
public static filter(collection: any, iteratees: Function) {
|
||
if (!Array.isArray(collection)) {
|
||
collection = Lodash._toArray(collection);
|
||
}
|
||
|
||
return collection.filter(iteratees);
|
||
}
|
||
|
||
/**
|
||
* 执行深比较来确定两者的值是否相等。
|
||
* @param {any}x
|
||
* @param {any}y
|
||
* @returns {boolean} 如果 两个值完全相同,那么返回 true,否则返回 false。
|
||
*/
|
||
public static isEqual(x: any, y: any): boolean {
|
||
var in1 = x instanceof Object;
|
||
var in2 = y instanceof Object;
|
||
if (!in1 || !in2) {
|
||
return x === y;
|
||
}
|
||
|
||
if (Object.keys(x).length !== Object.keys(y).length) {
|
||
return false;
|
||
}
|
||
|
||
for (var p in x) {
|
||
var a = x[p] instanceof Object;
|
||
var b = y[p] instanceof Object;
|
||
if (a && b) {
|
||
return Lodash.isEqual(x[p], y[p]);
|
||
} else if (x[p] !== y[p]) {
|
||
return false;
|
||
}
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* 接收一个要移除值的数组。
|
||
* @param {Array} array 修改的数组
|
||
* @param {Array} value 移除值的数组
|
||
* @param {Function} comparator comparator(比较器)调用每个元素。
|
||
* @returns
|
||
*/
|
||
public static pullAllWith(array: any[], value: any[], comparator: Function) {
|
||
value.forEach(function (item) {
|
||
var res = array.filter(function (n) {
|
||
return comparator(n, item);
|
||
});
|
||
|
||
res.forEach(function (item) {
|
||
var index = array.indexOf(item);
|
||
if (array.indexOf(item) !== -1) {
|
||
array.splice(index, 1);
|
||
}
|
||
});
|
||
});
|
||
|
||
return array;
|
||
}
|
||
|
||
/**
|
||
* 返回当前时间戳
|
||
* @returns
|
||
*/
|
||
public static now() {
|
||
return Date.now();
|
||
}
|
||
|
||
/**
|
||
* 接收一个要移除值的数组。
|
||
* @param {Array} array 修改的数组
|
||
* @param {Array} value 移除值的数组
|
||
* @returns
|
||
*/
|
||
public static pullAll(array: any[], value: any) {
|
||
value.forEach(function (item: any) {
|
||
var index = array.indexOf(item);
|
||
if (array.indexOf(item) !== -1) {
|
||
array.splice(index, 1);
|
||
}
|
||
});
|
||
|
||
return array;
|
||
}
|
||
|
||
/**
|
||
* 从右到左遍历集合中每一个元素的。
|
||
* @param {Array|Object} collection 一个用来迭代的集合.
|
||
* @param {Function} predicate 一个迭代函数
|
||
*/
|
||
public static forEachRight(collection: [] | {}, iteratee: Function) {
|
||
if (!Array.isArray(collection)) {
|
||
collection = Lodash._toArray(collection);
|
||
}
|
||
|
||
//@ts-ignore
|
||
for (var i = collection.length - 1; i >= 0; i--) {
|
||
//@ts-ignore
|
||
var ret = iteratee(collection[i]);
|
||
if (!ret) break;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 检查字符串string是否以 target 开头。
|
||
* @param {string} str 要检索的字符串。
|
||
* @param {string}target 要检查的字符串。
|
||
* @param {number}position 检索的位置。
|
||
* @returns
|
||
*/
|
||
public static startsWith(str: string, target: string, position: number) {
|
||
str = str.substr(position);
|
||
return str.startsWith(target);
|
||
}
|
||
|
||
/**
|
||
* 检查字符串string是否以 target 结束。
|
||
* @param {string} str 要检索的字符串。
|
||
* @param {string}target 要检查的字符串。
|
||
* @param {number}position 检索的位置。
|
||
* @returns
|
||
*/
|
||
public static endsWith(str: string, target: string, position: number) {
|
||
str = str.substr(position);
|
||
return str.endsWith(target);
|
||
}
|
||
|
||
/**
|
||
* 移除数组中predicate(断言)返回为真值的所有元素
|
||
* @param {Array} array 一个用来迭代的集合.
|
||
* @param {Function} predicate 一个迭代函数
|
||
* @returns
|
||
*/
|
||
public static remove(array: any[], predicate: Function) {
|
||
var result: any[] = [];
|
||
var indexes: any[] = [];
|
||
array.forEach(function (item, index) {
|
||
if (predicate(item)) {
|
||
result.push(item);
|
||
indexes.push(index);
|
||
}
|
||
});
|
||
|
||
Lodash._basePullAt(array, indexes);
|
||
return result;
|
||
}
|
||
|
||
private static _basePullAt(array: any[], indexes: any[]) {
|
||
var length = array ? indexes.length : 0;
|
||
var lastIndex = length - 1;
|
||
var previous;
|
||
|
||
while (length--) {
|
||
var index = indexes[length];
|
||
if (length === lastIndex || index !== previous) {
|
||
previous = index;
|
||
Array.prototype.splice.call(array, index, 1);
|
||
}
|
||
}
|
||
|
||
return array;
|
||
}
|
||
|
||
/**
|
||
* 返回第一个通过 predicate 判断为真值的元素的索引值
|
||
* @param {Array} array 一个用来迭代的集合.
|
||
* @param {Function} predicate 一个迭代函数
|
||
* @param {number} fromIndex 开始查找索引值
|
||
* @returns
|
||
*/
|
||
public static findIndex(array: any[], predicate: Function, fromIndex: number) {
|
||
array = array.slice(fromIndex);
|
||
var i;
|
||
if (typeof predicate === "function") {
|
||
for (i = 0; i < array.length; i++) {
|
||
if (predicate(array[i])) {
|
||
return i;
|
||
}
|
||
}
|
||
} else if (Array.isArray(predicate)) {
|
||
for (i = 0; i < array.length; i++) {
|
||
var key = predicate[0];
|
||
var vaule = true;
|
||
//@ts-ignore
|
||
if (predicate.length > 1) {
|
||
vaule = predicate[1];
|
||
}
|
||
|
||
if (array[i][key] === vaule) {
|
||
return i;
|
||
}
|
||
}
|
||
} else {
|
||
for (i = 0; i < array.length; i++) {
|
||
if (array[i] === predicate) {
|
||
return i;
|
||
}
|
||
}
|
||
}
|
||
|
||
return -1;
|
||
}
|
||
|
||
/**
|
||
* 创建一个新数组,将array与任何数组 或 值连接在一起。
|
||
* @returns
|
||
*/
|
||
public static concat() {
|
||
var length = arguments.length;
|
||
if (!length) {
|
||
return [];
|
||
}
|
||
|
||
var array = arguments[0];
|
||
var index = 1;
|
||
while (index < length) {
|
||
array = array.concat(arguments[index]);
|
||
index++;
|
||
}
|
||
|
||
return array;
|
||
}
|
||
|
||
/**
|
||
* 检查 value 是否是原始Number数值型 或者 对象。
|
||
* @param {any }value
|
||
* @returns
|
||
*/
|
||
public static isNumber(value: any) {
|
||
return typeof value === 'number';
|
||
}
|
||
|
||
/**
|
||
* 返回首次 value 在数组array中被找到的 索引值
|
||
* @param {Array}array
|
||
* @param {any}value
|
||
* @param {number} fromIndex
|
||
* @returns
|
||
*/
|
||
public static indexOf(array: any[], value: any, fromIndex: number) {
|
||
array = array.slice(fromIndex);
|
||
return array.indexOf(value);
|
||
}
|
||
|
||
/**
|
||
* 将 array 中的所有元素转换为由 separator 分隔的字符串。
|
||
* @param {any} array 要转换的数组
|
||
* @param {string} separator 分隔元素。
|
||
* @returns
|
||
*/
|
||
public static join(array: any[], separator: string) {
|
||
if (array === null) return '';
|
||
|
||
var result = '';
|
||
array.forEach(function (item) {
|
||
result += item + separator;
|
||
});
|
||
|
||
return result.substr(0, result.length - 1);
|
||
}
|
||
|
||
/**
|
||
* 根据separator 拆分字符串string。
|
||
* @param {string} str 要转换的数组
|
||
* @param {RegExp|string} separator 分隔元素。
|
||
* @param {number} limit 限制结果的数量。
|
||
* @returns
|
||
*/
|
||
public static split(str: string, separator: RegExp|string, limit: number) {
|
||
return str.split(separator, limit);
|
||
}
|
||
|
||
/**
|
||
* 计算 array 中的最大值。 如果 array 是 空的或者假值将会返回 undefined。
|
||
* @param {Array}array
|
||
* @returns
|
||
*/
|
||
public static max(array: any[]) {
|
||
if (array && array.length) {
|
||
var result;
|
||
for (var i = 0; i < array.length; i++) {
|
||
if (i === 0) {
|
||
result = array[0];
|
||
} else if (result < array[i]) {
|
||
result = array[i];
|
||
}
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
return undefined;
|
||
|
||
}
|
||
|
||
/**
|
||
* 创建一个切片数组,去除array前面的n个元素。(n默认值为1。)
|
||
* @param {Array}array : 要查询的数组。
|
||
* @param {number}n 要去除的元素个数。
|
||
* @returns
|
||
*/
|
||
public static drop(array: any[], n: number) {
|
||
var length = array === null ? 0 : array.length;
|
||
if (!length) {
|
||
return [];
|
||
}
|
||
|
||
return array.slice(n);
|
||
}
|
||
|
||
/**
|
||
* 将array递归为一维数组。
|
||
* @param {Array} arr
|
||
* @returns
|
||
*/
|
||
public static flattenDeep(arr: any[]): any {
|
||
return arr.reduce(function (prev: any[], cur: any[]) {
|
||
return prev.concat(Array.isArray(cur) ? Lodash.flattenDeep(cur) : cur);
|
||
}, [ ]);
|
||
}
|
||
|
||
/**
|
||
* 创建一个去重后的array数组副本。使用了SameValueZero 做等值比较。只有第一次出现的元素才会被保留。
|
||
* @param {Array} array
|
||
* @returns
|
||
*/
|
||
public static uniq(array: any[]) {
|
||
let result: any[] = [];
|
||
array.forEach(function (item) {
|
||
if (result.indexOf(item) === -1) {
|
||
result.push(item);
|
||
}
|
||
});
|
||
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* 检查 value 是否是 NaN。
|
||
* @param {any}value
|
||
* @returns
|
||
*/
|
||
public static isNaN(value: any) {
|
||
// An `NaN` primitive is the only value that is not equal to itself.
|
||
// Perform the `toStringTag` check first to avoid errors with some
|
||
// ActiveX objects in IE.
|
||
return Lodash.isNumber(value) && value !== +value;
|
||
}
|
||
|
||
/**
|
||
* 将数组(array)拆分成多个 size 长度的区块,并将这些区块组成一个新数组
|
||
* @param {Array}array
|
||
* @param {number}size
|
||
* @returns
|
||
*/
|
||
public static chunk(array: any[], size: number) {
|
||
var length = array === null ? 0 : array.length;
|
||
if (!length || size < 1) {
|
||
return [];
|
||
}
|
||
|
||
var result = [];
|
||
while (array.length > size) {
|
||
result.push(array.slice(0, size));
|
||
array = array.slice(size);
|
||
}
|
||
|
||
result.push(array);
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* 转换 value 为一个有限数字
|
||
* @param {any} value
|
||
* @returns
|
||
*/
|
||
public static toFinite(value: any) {
|
||
var INFINITY = 1 / 0;
|
||
var MAX_INTEGER = 1.7976931348623157e+308;
|
||
if (!value) {
|
||
return value === 0 ? value : 0;
|
||
}
|
||
value = Number(value);
|
||
if (value === INFINITY || value === -INFINITY) {
|
||
var sign = (value < 0 ? -1 : 1);
|
||
return sign * MAX_INTEGER;
|
||
}
|
||
return value === value ? value : 0;
|
||
}
|
||
|
||
/**
|
||
* 判断是否为对象
|
||
* @param {any}value
|
||
* @returns {boolean}
|
||
*/
|
||
public static isObject(value: any) {
|
||
var type = typeof value;
|
||
return value !== null && (type === 'object' || type === 'function');
|
||
}
|
||
|
||
public static MAX_SAFE_INTEGER = 9007199254740991;
|
||
|
||
/**
|
||
*
|
||
* @param value
|
||
* @returns
|
||
*/
|
||
public static isLength(value: any) {
|
||
return typeof value === 'number' &&
|
||
value > -1 && value % 1 === 0 && value <= Lodash.MAX_SAFE_INTEGER;
|
||
}
|
||
|
||
public static _isArrayLike(value: []) {
|
||
return value !== null && Lodash.isLength(value.length) /*&& !isFunction(value)*/;
|
||
}
|
||
|
||
/**
|
||
* 返回数组总符合条件的最大值
|
||
* @param {Array} array 一个用来迭代的集合.
|
||
* @param {Function} predicate 一个迭代函数
|
||
* @returns {Object} 返回最大值
|
||
*/
|
||
public static maxBy(array: any[], predicate: Function) {
|
||
if (array && array.length) {
|
||
var result;
|
||
var objResult;
|
||
for (var i = 0; i < array.length; i++) {
|
||
if (i === 0) {
|
||
result = predicate(array[0]);
|
||
objResult = array[0];
|
||
} else if (result < array[i]) {
|
||
result = (array[i]);
|
||
objResult = array[i];
|
||
}
|
||
}
|
||
|
||
return objResult;
|
||
}
|
||
|
||
return undefined;
|
||
|
||
}
|
||
|
||
/**
|
||
* 返回数组总符合条件的最小值
|
||
* @param {Array} array 一个用来迭代的集合.
|
||
* @param {Function} predicate 一个迭代函数
|
||
* @returns {Object} 返回最小值
|
||
*/
|
||
public static minBy(array: any[], predicate: Function) {
|
||
if (array && array.length) {
|
||
let result;
|
||
let objResult;
|
||
for (var i = 0; i < array.length; i++) {
|
||
if (i === 0) {
|
||
result = predicate(array[0]);
|
||
objResult = array[0];
|
||
} else if (result > array[i]) {
|
||
result = predicate(array[i]);
|
||
objResult = array[i];
|
||
}
|
||
}
|
||
|
||
return objResult;
|
||
}
|
||
|
||
return undefined;
|
||
|
||
}
|
||
/**
|
||
* 返回复合迭代函数的总和
|
||
* @param {Array|Object} collection 一个用来迭代的集合.
|
||
* @param {Function} predicate 一个迭代函数
|
||
* @returns {Object} 返回总和
|
||
*/
|
||
public static sumBy(collection: [] | {}, predicate: Function) {
|
||
let sum: number = 0;
|
||
for (let key in collection) {
|
||
//@ts-ignore
|
||
sum += predicate(collection[key]);
|
||
}
|
||
|
||
return sum;
|
||
}
|
||
|
||
/**
|
||
* 返回复合迭代函数的次数
|
||
* @param {Array|Object} collection 一个用来迭代的集合.
|
||
* @param {Function} predicate 一个迭代函数,用来转换key(键
|
||
* @returns {Object} 返回一个组成集合对象
|
||
*/
|
||
public static countBy(collection: [] | {}, predicate: Function) {
|
||
let objRet: {[key: string]: number} = {};
|
||
for (let key in collection) {
|
||
let value: any = predicate(key);
|
||
if (objRet.hasOwnProperty(value)) {
|
||
objRet[value] += 1;
|
||
} else {
|
||
objRet[value] = 1;
|
||
}
|
||
}
|
||
|
||
return objRet;
|
||
}
|
||
|
||
}
|