diff --git a/lib/array/randomItem.js b/lib/array/randomItem.js new file mode 100644 index 0000000..62d314b --- /dev/null +++ b/lib/array/randomItem.js @@ -0,0 +1,26 @@ +/** + * 随机取数组中的元素 + * @author XiaoXinYo + * @category 数组 + * @param {Array} array 数组 + * @param {number} number 数量 + * @param {Boolean} repeat 是否允许重复 + * @returns {Array} 返回取出元素的数组 + */ + +export default (array, number = 1, repeat = false) => { + const temp_array = [...new Set(array)]; + if (!repeat && number > temp_array.length) { + throw new Error('所需数量超出数组的不重复元素数量'); + } + + const result = []; + for (let i = 0; i < number; i++) { + let itemIndex = Math.floor(Math.random() * temp_array.length); + result.push(temp_array[itemIndex]); + if (!repeat) { + temp_array.splice(itemIndex, 1); + } + } + return result; +}; diff --git a/lib/browser/irregularSorting.js b/lib/browser/irregularSorting.js new file mode 100644 index 0000000..a9f732f --- /dev/null +++ b/lib/browser/irregularSorting.js @@ -0,0 +1,55 @@ +/** + * @name irregularSorting + * @author wjr13294670259@163.com + * @description 无规则图片排序 + * @param { * Array} picList 图片列表 + * @param { * dom } 在dom 上展示 + * @param { * num } 每行展示个数 + * @category 浏览器 + */ + +function irregularSorting(picList, containerDom, num) { + if (!containerDom || !picList.length) return; + let screenWidth = containerDom.clientWidth; + picList.forEach(async (item, index) => { + const img = document.createElement("img"); + img.src = item.url; + img.style.width = screenWidth / (num + 0.8) + "px"; + img.style.position = "absolute"; + img.loading = "lazy"; + img.style.left = !(index % num) + ? "10px" + : (screenWidth / num) * (index % num) + 10 + "px"; + + if (index < num) { + img.style.top = containerDom.offsetTop + "px"; + } else { + let topAndLeft = []; + for (let i = 0; i < containerDom.childNodes.length; i++) { + topAndLeft.push({ + left: containerDom.childNodes[i].offsetLeft, + top: + containerDom.childNodes[i].offsetTop + + containerDom.childNodes[i].offsetHeight, + }); + } + const allListSort = topAndLeft.sort((a, b) => a.top - b.top); + const needList = allListSort.slice( + allListSort.length - num, + allListSort.length + ); + const finallyTop = needList.sort((a, b) => a.top - b.top)[0]; + img.style.top = finallyTop.top + 10 + "px"; + img.style.left = finallyTop.left + "px"; + } + await containerDom.appendChild(img); + }); + let heightList = []; + for (let i = 0; i < containerDom.children.length; i++) { + heightList.push( + containerDom.childNodes[i].offsetTop + + containerDom.childNodes[i].offsetHeight + ); + } + containerDom.style.height = heightList.sort((a, b) => b - a)[0] + "px"; +} diff --git a/lib/faker/generateChineseName.js b/lib/faker/generateChineseName.js new file mode 100644 index 0000000..ba10dec --- /dev/null +++ b/lib/faker/generateChineseName.js @@ -0,0 +1,22 @@ +/** + * 常见的姓氏 + */ +const surnames = ["赵", "钱", "孙", "李", "周", "吴", "郑", "王"]; + +/** + * 常见的名字 + */ +const names = ["子璇", "淼", "国栋", "夫子", "瑞堂", "甜", "敏", "尚", "国贤", "贺祥", "晨涛", "昊轩", "易轩", "辰益", "帆", "冉", "瑾", "春", "瑾昆", "春齐", "杨", "文昊", "东雄", "霖", "浩晨", "熙涵", "溶溶", "冰枫", "欣宜", "豪", "欣慧", "建政", "美欣", "淑慧", "文轩", "杰", "欣源", "忠林", "榕润", "欣汝", "慧嘉", "新建", "建林", "亦菲", "林", "冰洁", "佳欣", "涵涵", "禹辰", "淳美", "泽惠", "伟洋", "涵越", "润丽", "翔", "淑华", "晶莹", "凌晶", "苒溪", "雨涵", "嘉怡", "佳毅", "子辰", "佳琪", "紫轩", "瑞辰", "昕蕊", "萌", "明远", "欣宜", "泽远", "欣怡", "佳怡", "佳惠", "晨茜", "晨璐", "运昊", "汝鑫", "淑君", "晶滢", "润莎", "榕汕", "佳钰", "佳玉", "晓庆", "一鸣", "语晨", "添池", "添昊", "雨泽", "雅晗", "雅涵", "清妍", "诗悦", "嘉乐", "晨涵", "天赫", "玥傲", "佳昊", "天昊", "萌萌", "若萌"]; +/** + * 生成一个姓名 + * @author xiaoxiaohuayu + * @example + * console.log(generateChineseName()); // 输出: 王国栋 + * @returns {String} 返回一个随机的中文姓名 + * @summary 应用场景:用于生成测试数据 + */ +export function generateChineseName () { + const surname = surnames[Math.floor(Math.random() * surnames.length)]; + const name = names[Math.floor(Math.random() * names.length)]; + return surname + name +} diff --git a/lib/faker/generateLicensePlateNumber.js b/lib/faker/generateLicensePlateNumber.js new file mode 100644 index 0000000..77a1835 --- /dev/null +++ b/lib/faker/generateLicensePlateNumber.js @@ -0,0 +1,26 @@ +/** + * 生成一个车牌号 + * @author xiaoxiaohuayu + * @example + * console.log(generateLicensePlateNumber()); // 输出: 闽ASXRG4 + * @summary 应用场景:用于生成测试数据 + * @param {Number} total 生成车牌号的位数 (新能源车牌号为6位,普通车牌号为5位) 默认5位 + * @returns {String} 返回一个随机的车牌号 + */ + const dicingChar = (series) => { + return series[~~(Math.random() * series.length)] + } +export function generateLicensePlateNumber (total = 5) { + const stateList = '京津冀晋辽吉沪苏浙皖闽琼赣鲁豫鄂湘粤渝川贵云陕甘蒙黑桂藏青宁新' + const charList = 'ABCDEFGHJKLMNQPRSTUVWXYZ' + const numList = '1234567890' + const halfList = [charList, numList] + const state = dicingChar(stateList) + const city = dicingChar(charList) + let sequence = '' + while (total--) { + sequence += dicingChar(halfList[Math.round(Math.random())]) + } + // console.log(`${state}${city}${sequence}`) + return `${state}${city}${sequence}` +} diff --git a/lib/faker/generateMobleTel.js b/lib/faker/generateMobleTel.js new file mode 100644 index 0000000..bb7428d --- /dev/null +++ b/lib/faker/generateMobleTel.js @@ -0,0 +1,23 @@ +/** + * 生成一个手机号 + * @author xiaoxiaohuayu + * @example + * console.log(generateMobleTel()); // 输出: 15105113629 + * @returns {String} 返回一个随机的手机号 + * @summary 应用场景:用于生成测试数据 + */ +export function generateMobleTel () { + // China Mobile 移动号段 + const c_Mobile = ['134', '147', '159', '184', '135', '150', '165', '187', '136', '151', '172', '188', '137', '152', '178', '195', '138', '157', '182', '197', '139', '158', '183', '198']; + // China Unicom 联通号段 + const c_Unicom = ['130', '156', '185', '131', '166', '186', '132', '167', '196', '145', '171', '146', '175', '155', '176'] + // China Telecom 电信号段 + const c_Telecom = ['133', '177', '199', '149', '180', '153', '181', '162', '189', '173', '191', '174', '193'] + const prefixes = c_Mobile.concat(c_Unicom, c_Telecom) + const prefix = prefixes[Math.floor(prefixes.length * Math.random())]; + let body = ""; + for (let i = 0; i < 8; i++) { + body += Math.floor(Math.random() * 10); + } + return prefix + body; +} diff --git a/lib/is/boolean.js b/lib/is/boolean.js index 118d6e0..c3616d3 100644 --- a/lib/is/boolean.js +++ b/lib/is/boolean.js @@ -1,4 +1,4 @@ -import { yd_internal_getValueType } from '../internal/getValueType.js'; +import getValueType from '../internal/getValueType.js'; /** * 判断是否是布尔值 * @author 陈随易 @@ -7,5 +7,5 @@ import { yd_internal_getValueType } from '../internal/getValueType.js'; * @returns {Boolean} 返回是否是布尔值 */ export default (value) => { - return value === true || value === false || yd_internal_getValueType(value) === '[object Boolean]'; + return value === true || value === false || getValueType(value) === '[object Boolean]'; }; diff --git a/lib/is/date.js b/lib/is/date.js index f72898d..fb3e8d3 100644 --- a/lib/is/date.js +++ b/lib/is/date.js @@ -1,4 +1,4 @@ -import { yd_internal_getValueType } from '../internal/getValueType.js'; +import getValueType from '../internal/getValueType.js'; /** * 判断是否是日期 * @author 陈随易 @@ -7,5 +7,5 @@ import { yd_internal_getValueType } from '../internal/getValueType.js'; * @returns {Boolean} 返回是否是日期 */ export default (value) => { - return yd_internal_getValueType(value) === '[object Date]'; + return getValueType(value) === '[object Date]'; }; diff --git a/lib/is/function.js b/lib/is/function.js index 015b31c..240037f 100644 --- a/lib/is/function.js +++ b/lib/is/function.js @@ -1,4 +1,4 @@ -import { yd_internal_getValueType } from '../internal/getValueType.js'; +import getValueType from '../internal/getValueType.js'; /** * 判断是否是函数 * @author 陈随易 @@ -7,6 +7,6 @@ import { yd_internal_getValueType } from '../internal/getValueType.js'; * @returns {Boolean} 返回是否是函数 */ export default (value) => { - const tag = yd_internal_getValueType(value); + const tag = getValueType(value); return tag === '[object Function]' || tag === '[object AsyncFunction]'; }; diff --git a/lib/is/map.js b/lib/is/map.js index 02f5cab..6481533 100644 --- a/lib/is/map.js +++ b/lib/is/map.js @@ -1,4 +1,4 @@ -import { yd_internal_getValueType } from '../internal/getValueType.js'; +import getValueType from '../internal/getValueType.js'; /** * 判断是否是Map值 * @author 陈随易 @@ -7,5 +7,5 @@ import { yd_internal_getValueType } from '../internal/getValueType.js'; * @returns {Boolean} 返回是否是Map值 */ export default (value) => { - return yd_internal_getValueType(value) === '[object Map]'; + return getValueType(value) === '[object Map]'; }; diff --git a/lib/is/regexp.js b/lib/is/regexp.js index 04d5bc7..49606c7 100644 --- a/lib/is/regexp.js +++ b/lib/is/regexp.js @@ -1,4 +1,4 @@ -import { yd_internal_getValueType } from '../internal/getValueType.js'; +import getValueType from '../internal/getValueType.js'; /** * 判断是否是正则表达式 * @author 陈随易 @@ -7,5 +7,5 @@ import { yd_internal_getValueType } from '../internal/getValueType.js'; * @returns {Boolean} 返回是否是正则表达式 */ export default (value) => { - return yd_internal_getValueType(value) === '[object RegExp]'; + return getValueType(value) === '[object RegExp]'; }; diff --git a/lib/is/set.js b/lib/is/set.js index 098b8b3..d7d4748 100644 --- a/lib/is/set.js +++ b/lib/is/set.js @@ -1,4 +1,4 @@ -import { yd_internal_getValueType } from '../internal/getValueType.js'; +import getValueType from '../internal/getValueType.js'; /** * 判断是否是Set值 * @author 陈随易 @@ -7,5 +7,5 @@ import { yd_internal_getValueType } from '../internal/getValueType.js'; * @returns {Boolean} 返回是否是Set值 */ export default (value) => { - return yd_internal_getValueType(value) === '[object Set]'; + return getValueType(value) === '[object Set]'; }; diff --git a/lib/is/symbol.js b/lib/is/symbol.js index 157e733..c2e28c6 100644 --- a/lib/is/symbol.js +++ b/lib/is/symbol.js @@ -1,4 +1,4 @@ -import { yd_internal_getValueType } from '../internal/getValueType.js'; +import getValueType from '../internal/getValueType.js'; /** * 判断是否是Symbol值 * @author 陈随易 @@ -7,5 +7,5 @@ import { yd_internal_getValueType } from '../internal/getValueType.js'; * @returns {Boolean} 返回是否是Symbol值 */ export default (value) => { - return yd_internal_getValueType(value) === '[object Symbol]'; + return getValueType(value) === '[object Symbol]'; }; diff --git a/lib/is/weakMap.js b/lib/is/weakMap.js index 8f77959..d525584 100644 --- a/lib/is/weakMap.js +++ b/lib/is/weakMap.js @@ -1,4 +1,4 @@ -import { yd_internal_getValueType } from '../internal/getValueType.js'; +import getValueType from '../internal/getValueType.js'; /** * 判断是否是WeakMap值 * @author 陈随易 @@ -7,5 +7,5 @@ import { yd_internal_getValueType } from '../internal/getValueType.js'; * @returns {Boolean} 返回是否是WeakMap值 */ export default (value) => { - return yd_internal_getValueType(value) === '[object WeakMap]'; + return getValueType(value) === '[object WeakMap]'; }; diff --git a/lib/is/weakSet.js b/lib/is/weakSet.js index 1a7fd94..f4d9be6 100644 --- a/lib/is/weakSet.js +++ b/lib/is/weakSet.js @@ -1,4 +1,4 @@ -import { yd_internal_getValueType } from '../internal/getValueType.js'; +import getValueType from '../internal/getValueType.js'; /** * 判断是否是WeakSet值 * @author 陈随易 @@ -7,5 +7,5 @@ import { yd_internal_getValueType } from '../internal/getValueType.js'; * @returns {Boolean} 返回是否是WeakSet值 */ export default (value) => { - return yd_internal_getValueType(value) === '[object WeakSet]'; + return getValueType(value) === '[object WeakSet]'; }; diff --git a/lib/object/pickBy.js b/lib/object/pickBy.js new file mode 100644 index 0000000..b91c954 --- /dev/null +++ b/lib/object/pickBy.js @@ -0,0 +1,34 @@ +import isObject from '../../lib/is/object'; +import isFunction from '../../lib/is/function'; + +/** + * 对象属性摘取 + * @author imddc + * @category 对象 + * @param {Object} obj 对象数据 + * @param {Funcion} fn 获取字段的方式 + * @returns {Object} 摘取对象中的指定字段 + */ +export default (obj, fn) => { + if (!isObject(obj)) { + throw new Error('obj must be an object'); + } + + if (!isFunction(fn)) { + throw new Error('fn must be an function'); + } + + if (Object.keys(obj).length === 0) { + return obj; + } + + const picked = {}; + for (const key in obj) { + if (obj.hasOwnProperty(key)) { + if (fn(obj[key])) { + picked[key] = obj[key]; + } + } + } + return picked; +}; diff --git a/test/array/randomItem.test.js b/test/array/randomItem.test.js new file mode 100644 index 0000000..b82be6d --- /dev/null +++ b/test/array/randomItem.test.js @@ -0,0 +1,39 @@ +import { describe, it, expect } from 'vitest'; +import yd_array_randomItem from '../../lib/array/randomItem.js'; + +describe('yd_array_randomItem', () => { + it('returns specified number of items', () => { + const array = [1, 2, 3, 4, 5]; + const result = [...new Set(yd_array_randomItem(array, 3))]; + result.forEach((item) => { + expect(array).toContain(item); + }); + expect(result).toHaveLength(3); + }); + + it('returns repeating items when repeat is true', () => { + const array = [1, 2, 3, 4, 5]; + const result = yd_array_randomItem(array, 3, true); + result.forEach((item) => { + expect(array).toContain(item); + }); + expect(result).toHaveLength(3); + }); + + it('when the required quantity exceeds the number of non repeating elements in the array and non repeating is required, an exception will be raised', () => { + const array = [1, 2, 3, 3]; + const testFunc = () => { + yd_array_randomItem(array, 4, false); + }; + expect(testFunc).toThrow('所需数量超出数组的不重复元素数量'); + }); + + it('when repeat is true and the required number exceeds the number of non repeating elements in the array, return a duplicate item', () => { + const array = [1, 2, 3, 3]; + const result = yd_array_randomItem(array, 4, true); + result.forEach((item) => { + expect(array).toContain(item); + }); + expect(result).toHaveLength(4); + }); +}); diff --git a/test/is/odd.test.js b/test/is/odd.test.js index 00a9ef1..dc4da89 100644 --- a/test/is/odd.test.js +++ b/test/is/odd.test.js @@ -1,24 +1,24 @@ -import { describe, it, expect } from 'vitest'; -import yd_is_odd from '../../lib/is/odd'; +import { describe, expect, it } from 'vitest' +import yd_is_odd from '../../lib/is/odd' describe('yd_is_odd', () => { it('should be `true`', () => { - expect(yd_is_odd(13)).toBeTruthy(); - expect(yd_is_odd(-13)).toBeTruthy(); - }); + expect(yd_is_odd(13)).toBeTruthy() + expect(yd_is_odd(-13)).toBeTruthy() + }) it('should be `false`', () => { - expect(isOdd(0)).toBeFalsy(); - expect(isOdd(2)).toBeFalsy(); - expect(isOdd(-2)).toBeFalsy(); - }); + expect(yd_is_odd(0)).toBeFalsy() + expect(yd_is_odd(2)).toBeFalsy() + expect(yd_is_odd(-2)).toBeFalsy() + }) it('should throw Error', () => { - expect(() => isOdd(true)).toThrowError('value must be a number'); - expect(() => isOdd(Symbol())).toThrowError('value must be a number'); - expect(() => isOdd([])).toThrowError('value must be a number'); - expect(() => isOdd({})).toThrowError('value must be a number'); - expect(() => isOdd(new Date())).toThrowError('value must be a number'); + expect(() => yd_is_odd(true)).toThrowError('value must be a number') + expect(() => yd_is_odd(Symbol(''))).toThrowError('value must be a number') + expect(() => yd_is_odd([])).toThrowError('value must be a number') + expect(() => yd_is_odd({})).toThrowError('value must be a number') + expect(() => yd_is_odd(new Date())).toThrowError('value must be a number') // ... - }); -}); + }) +}) diff --git a/test/object/pickBy.test.js b/test/object/pickBy.test.js new file mode 100644 index 0000000..4249455 --- /dev/null +++ b/test/object/pickBy.test.js @@ -0,0 +1,30 @@ +import { describe, it, expect } from 'vitest'; +import pickBy from '../../lib/object/pickBy'; +import isNumber from '../../lib/is/number'; +import isBoolean from '../../lib/is/boolean'; + +describe('pickBy', () => { + it('should return number member', () => { + const obj = { a: 1, b: '2', c: 3 }; + const res = { a: 1, c: 3 }; + expect(pickBy(obj, isNumber)).toEqual(res); + }); + + it('should return Boolean member', () => { + const obj = { a: true, b: '2', c: 3, d: false, e: undefined, f: null, g: Symbol(), h: {}, i: [] }; + const res = { a: true, d: false }; + expect(pickBy(obj, isBoolean)).toEqual(res); + }); + + it('should return Empty member', () => { + const obj = {}; + const res = {}; + expect(pickBy(obj, (_) => _)).toEqual(res); + }); + + it('should throw Error', () => { + expect(() => pickBy([], (_) => _)).toThrow('obj must be an object'); + + expect(() => pickBy({ a: 1, b: 2, c: 3 }, {})).toThrow('fn must be an function'); + }); +});