@yoooloo42/bean 1.0.16 → 1.0.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs.js +2 -0
- package/dist/index.cjs.js.map +1 -0
- package/dist/index.esm.js +2 -0
- package/dist/index.esm.js.map +1 -0
- package/package.json +37 -24
- package/src/GBT/gbt2260code2.js +0 -40
- package/src/GBT/gbt2260code4.js +0 -413
- package/src/GBT/gbt2260code6.js +0 -3566
- package/src/GBT/gbt2659.js +0 -66
- package/src/GBT/gbt3304.js +0 -62
- package/src/GBT/index.js +0 -20
- package/src/index.js +0 -11
- package/src/unclassified/dateFormat.js +0 -86
- package/src/unclassified/deepClone.js +0 -363
- package/src/unclassified/index.js +0 -20
- package/src/unclassified/random.js +0 -117
- package/src/unclassified/regexp.js +0 -175
- package/src/unclassified/sort.js +0 -243
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 在指定的字符集内生成一个指定长度的随机字符串。
|
|
3
|
-
*
|
|
4
|
-
* @param {number} length - 随机字符串的所需长度。
|
|
5
|
-
* @param {string} characterSet - 用于生成字符串的字符集(如 '0123456789abcdef')。
|
|
6
|
-
* @returns {string} - 生成的随机字符串。
|
|
7
|
-
* @throws {Error} - 如果长度不是正数或字符集为空。
|
|
8
|
-
*/
|
|
9
|
-
function random(length, characterSet) {
|
|
10
|
-
// 1. 输入校验
|
|
11
|
-
if (typeof length !== 'number' || length <= 0) {
|
|
12
|
-
throw new Error("长度参数必须是一个大于零的数字。");
|
|
13
|
-
}
|
|
14
|
-
if (typeof characterSet !== 'string' || characterSet.length === 0) {
|
|
15
|
-
throw new Error("字符集参数必须是一个非空字符串。");
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
const characterSetLength = characterSet.length;
|
|
19
|
-
let result = '';
|
|
20
|
-
|
|
21
|
-
// 2. 循环 'length' 次,每次随机选择一个字符
|
|
22
|
-
for (let i = 0; i < length; i++) {
|
|
23
|
-
// 随机选择字符的索引
|
|
24
|
-
const randomIndex = Math.floor(Math.random() * characterSetLength);
|
|
25
|
-
|
|
26
|
-
// 将随机选中的字符添加到结果字符串中
|
|
27
|
-
result += characterSet.charAt(randomIndex);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
return result;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* 随机生成一个符合常见验证码规则(4-8位,数字+大小写字母)的字符串。
|
|
35
|
-
* @returns {string} - 随机生成的验证码字符串。
|
|
36
|
-
*/
|
|
37
|
-
function vercode() {
|
|
38
|
-
// 定义所有允许的字符集 (数字 0-9, 小写字母 a-z, 大写字母 A-Z)
|
|
39
|
-
const characterSet = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
|
40
|
-
const characterSetLength = characterSet.length;
|
|
41
|
-
|
|
42
|
-
// 随机确定验证码的长度,范围在 [4, 8] 之间
|
|
43
|
-
// Math.random() * (max - min + 1) + min
|
|
44
|
-
const minLength = 4;
|
|
45
|
-
const maxLength = 8;
|
|
46
|
-
const length = Math.floor(Math.random() * (maxLength - minLength + 1)) + minLength;
|
|
47
|
-
|
|
48
|
-
let result = '';
|
|
49
|
-
|
|
50
|
-
// 循环 'length' 次,每次随机从 characterSet 中选择一个字符
|
|
51
|
-
for (let i = 0; i < length; i++) {
|
|
52
|
-
// 随机选择字符的索引
|
|
53
|
-
const randomIndex = Math.floor(Math.random() * characterSetLength);
|
|
54
|
-
|
|
55
|
-
// 将随机选中的字符添加到结果字符串中
|
|
56
|
-
result += characterSet.charAt(randomIndex);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
return result;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* 随机生成一个固定 6 位长度、包含数字和大小写字母的验证码字符串。
|
|
64
|
-
* @returns {string} - 随机生成的 6 位验证码字符串。
|
|
65
|
-
*/
|
|
66
|
-
function vercode6(length = 6) {
|
|
67
|
-
// 定义所有允许的字符集 (数字 0-9, 小写字母 a-z, 大写字母 A-Z)
|
|
68
|
-
const characterSet = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
|
69
|
-
const characterSetLength = characterSet.length;
|
|
70
|
-
|
|
71
|
-
let result = '';
|
|
72
|
-
// 循环 6 次,每次随机从 characterSet 中选择一个字符
|
|
73
|
-
for (let i = 0; i < length; i++) {
|
|
74
|
-
// 随机选择字符的索引
|
|
75
|
-
const randomIndex = Math.floor(Math.random() * characterSetLength);
|
|
76
|
-
|
|
77
|
-
// 将随机选中的字符添加到结果字符串中
|
|
78
|
-
result += characterSet.charAt(randomIndex);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
return result;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* 随机生成一个固定 6 位长度、只包含数字的验证码字符串。
|
|
86
|
-
* @returns {string} - 随机生成的 6 位验证码字符串。
|
|
87
|
-
*/
|
|
88
|
-
function vercode6N(length = 6) {
|
|
89
|
-
// 定义所有允许的字符集 (数字 0-9, 小写字母 a-z, 大写字母 A-Z)
|
|
90
|
-
const characterSet = '0123456789';
|
|
91
|
-
const characterSetLength = characterSet.length;
|
|
92
|
-
|
|
93
|
-
let result = '';
|
|
94
|
-
// 循环 6 次,每次随机从 characterSet 中选择一个字符
|
|
95
|
-
for (let i = 0; i < length; i++) {
|
|
96
|
-
// 随机选择字符的索引
|
|
97
|
-
const randomIndex = Math.floor(Math.random() * characterSetLength);
|
|
98
|
-
|
|
99
|
-
// 将随机选中的字符添加到结果字符串中
|
|
100
|
-
result += characterSet.charAt(randomIndex);
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
return result;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
export {
|
|
107
|
-
random,
|
|
108
|
-
vercode,
|
|
109
|
-
vercode6,
|
|
110
|
-
vercode6N
|
|
111
|
-
}
|
|
112
|
-
export default {
|
|
113
|
-
random,
|
|
114
|
-
vercode,
|
|
115
|
-
vercode6,
|
|
116
|
-
vercode6N
|
|
117
|
-
}
|
|
@@ -1,175 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 校验字符串是否为有效的中国大陆手机号码(宽松校验)
|
|
3
|
-
* 规则:以 1 开头,后面跟 10 个数字,共 11 位。
|
|
4
|
-
*
|
|
5
|
-
* @param {string} str - 需要校验的字符串
|
|
6
|
-
* @returns {boolean} - 如果是有效的手机号格式,返回 true;否则返回 false。
|
|
7
|
-
*/
|
|
8
|
-
function cellphone(str) {
|
|
9
|
-
if (typeof str !== 'string' || str.length === 0) {
|
|
10
|
-
return false;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
// 正则表达式:
|
|
14
|
-
// ^ -> 匹配字符串的开始
|
|
15
|
-
// 1 -> 匹配数字 1
|
|
16
|
-
// \d{10} -> 匹配任何数字 (0-9) 十次
|
|
17
|
-
// $ -> 匹配字符串的结束
|
|
18
|
-
const regex = /^1\d{10}$/;
|
|
19
|
-
|
|
20
|
-
return regex.test(str);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* 校验字符串是否为有效的电子邮件地址格式。
|
|
25
|
-
* * 这个正则是一个常用的、相对宽松但有效的校验模式。
|
|
26
|
-
* 它覆盖了:
|
|
27
|
-
* 1. 局部部分(@符号之前):允许字母、数字、点号(.)、下划线(_)、连字符(-)。
|
|
28
|
-
* 2. 域名部分(@符号之后):至少包含一级域名和顶级域名,允许字母、数字、连字符。
|
|
29
|
-
* 3. 顶级域名(最后一段):必须是至少两位字母(如 .com, .cn, .co.uk)。
|
|
30
|
-
*
|
|
31
|
-
* @param {string} str - 需要校验的字符串
|
|
32
|
-
* @returns {boolean} - 如果是有效的电子邮箱格式,返回 true;否则返回 false。
|
|
33
|
-
*/
|
|
34
|
-
function email(str) {
|
|
35
|
-
if (typeof str !== 'string' || str.length === 0) {
|
|
36
|
-
return false;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
// 正则表达式解释:
|
|
40
|
-
// ^ -> 匹配字符串的开始
|
|
41
|
-
// [a-zA-Z0-9._-]+ -> 局部部分:匹配一个或多个字母、数字、点(.)、下划线(_)或连字符(-)
|
|
42
|
-
// @ -> 必须包含 @ 符号
|
|
43
|
-
// [a-zA-Z0-9.-]+ -> 域名部分:匹配一个或多个字母、数字、点(.)或连字符(-)
|
|
44
|
-
// \. -> 必须包含一个点号(用于分隔域名和顶级域名)
|
|
45
|
-
// [a-zA-Z]{2,6} -> 顶级域名:匹配 2 到 6 个字母 (如 com, cn, info, museum)
|
|
46
|
-
// (?:\.[a-zA-Z]{2,6})? -> (可选) 匹配二级或多级域名(如 .co.uk)
|
|
47
|
-
// $ -> 匹配字符串的结束
|
|
48
|
-
|
|
49
|
-
const emailRegex = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}(?:\.[a-zA-Z]{2,6})?$/;
|
|
50
|
-
|
|
51
|
-
return emailRegex.test(str);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* 校验字符串是否符合中等强度的登录密码要求。
|
|
56
|
-
* 规则:
|
|
57
|
-
* 1. 长度在 8 到 16 位之间。
|
|
58
|
-
* 2. 必须包含大小写字母、数字、特殊符号 (@ $ ! % * # ? &) 中的至少两种组合。
|
|
59
|
-
*
|
|
60
|
-
* @param {string} str - 需要校验的密码字符串
|
|
61
|
-
* @returns {boolean} - 如果符合密码要求,返回 true;否则返回 false。
|
|
62
|
-
*/
|
|
63
|
-
function password(str) {
|
|
64
|
-
if (typeof str !== 'string' || str.length === 0) {
|
|
65
|
-
return false;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
// --- 1. 长度校验 ---
|
|
69
|
-
// 匹配 8 到 16 位任何非换行符的字符
|
|
70
|
-
const lengthRegex = /^.{8,16}$/;
|
|
71
|
-
if (!lengthRegex.test(str)) {
|
|
72
|
-
// console.log("密码长度不符合要求(需 8-16 位)。");
|
|
73
|
-
return false;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
// --- 2. 字符组合校验(使用正向预查 Lookaheads) ---
|
|
77
|
-
|
|
78
|
-
// 正向预查的定义:
|
|
79
|
-
// (?=.*[a-z]) : 必须包含小写字母
|
|
80
|
-
// (?=.*[A-Z]) : 必须包含大写字母
|
|
81
|
-
// (?=.*\d) : 必须包含数字
|
|
82
|
-
// (?=.*[@$!%*#?&]) : 必须包含特殊符号
|
|
83
|
-
|
|
84
|
-
// 构造四个组合的正则,只要满足任意两个即可
|
|
85
|
-
|
|
86
|
-
let count = 0;
|
|
87
|
-
|
|
88
|
-
// 检查是否包含小写字母
|
|
89
|
-
if (/(?=.*[a-z])/.test(str)) {
|
|
90
|
-
count++;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
// 检查是否包含大写字母
|
|
94
|
-
if (/(?=.*[A-Z])/.test(str)) {
|
|
95
|
-
count++;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
// 检查是否包含数字
|
|
99
|
-
if (/(?=.*\d)/.test(str)) {
|
|
100
|
-
count++;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
// 检查是否包含特殊符号
|
|
104
|
-
if (/(?=.*[@$!%*#?&])/.test(str)) {
|
|
105
|
-
count++;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
// 最终判断:至少包含两种类型的字符
|
|
109
|
-
const isCombinationValid = count >= 2;
|
|
110
|
-
|
|
111
|
-
// console.log(`满足的字符类型数量: ${count}`);
|
|
112
|
-
return isCombinationValid;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
/**
|
|
116
|
-
* 验证一个字符串是否符合常见的验证码规则。
|
|
117
|
-
* 规则:长度在 4 到 8 位之间,内容只包含数字和大小写字母。
|
|
118
|
-
* * @param {string} str - 需要验证的字符串。
|
|
119
|
-
* @returns {boolean} - 如果符合规则返回 true,否则返回 false。
|
|
120
|
-
*/
|
|
121
|
-
function vercode(str) {
|
|
122
|
-
// 1. 检查输入是否为字符串
|
|
123
|
-
if (typeof str !== 'string') {
|
|
124
|
-
return false;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
// 2. 正则表达式解释:
|
|
128
|
-
// ^ 表示字符串的开始
|
|
129
|
-
// [0-9a-zA-Z] 表示字符必须是数字(0-9)或大小写字母(a-z, A-Z)
|
|
130
|
-
// {4,8} 表示字符的长度必须在 4 到 8 位之间(包含 4 和 8)
|
|
131
|
-
// $ 表示字符串的结束
|
|
132
|
-
const Regex = /^[0-9a-zA-Z]{4,8}$/;
|
|
133
|
-
|
|
134
|
-
// 3. 执行匹配
|
|
135
|
-
return Regex.test(str);
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
/**
|
|
139
|
-
* 验证一个字符串是否符合固定的 6 位验证码规则。
|
|
140
|
-
* 规则:长度必须是 6 位,内容只包含数字和大小写字母。
|
|
141
|
-
* @param {string} str - 需要验证的字符串。
|
|
142
|
-
* @param {number} length - 验证码必须具备的固定长度
|
|
143
|
-
* @returns {boolean} - 如果符合规则返回 true,否则返回 false。
|
|
144
|
-
*/
|
|
145
|
-
function vercode6(str, length=6) {
|
|
146
|
-
// 1. 检查输入是否为字符串(可选,但推荐)
|
|
147
|
-
if (typeof str !== 'string') {
|
|
148
|
-
return false;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
// 2. 正则表达式解释:
|
|
152
|
-
// ^ 表示字符串的开始
|
|
153
|
-
// [0-9a-zA-Z] 表示字符必须是数字(0-9)或大小写字母(a-z, A-Z)
|
|
154
|
-
// {6} 表示字符的长度必须恰好是 6 位
|
|
155
|
-
// $ 表示字符串的结束
|
|
156
|
-
const Regex = new RegExp('^[0-9a-zA-Z]{' + length + '}$');
|
|
157
|
-
|
|
158
|
-
// 3. 执行匹配
|
|
159
|
-
return Regex.test(str);
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
export {
|
|
163
|
-
cellphone,
|
|
164
|
-
email,
|
|
165
|
-
password,
|
|
166
|
-
vercode,
|
|
167
|
-
vercode6
|
|
168
|
-
}
|
|
169
|
-
export default {
|
|
170
|
-
cellphone,
|
|
171
|
-
email,
|
|
172
|
-
password,
|
|
173
|
-
vercode,
|
|
174
|
-
vercode6
|
|
175
|
-
}
|
package/src/unclassified/sort.js
DELETED
|
@@ -1,243 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 对一个由简单数据类型的值(数值、字符串、日期等)组成的数组进行排序。
|
|
3
|
-
*
|
|
4
|
-
* @param {Array<any>} arr 待排序的简单数据类型数组。
|
|
5
|
-
* @param {'asc' | 'desc'} direction 排序方向:'asc'(升序)或 'desc'(降序)。
|
|
6
|
-
* @param {'locale' | 'natural'} sortType 排序类型:
|
|
7
|
-
* - 'locale': 字典顺序排序。
|
|
8
|
-
* - 'natural': 自然顺序排序。
|
|
9
|
-
* @returns {Array<any>} 排序后的新数组。
|
|
10
|
-
*/
|
|
11
|
-
function sortSimpleArray(arr, direction, sortType) {
|
|
12
|
-
// 1. 参数校验 (简化)
|
|
13
|
-
if (!Array.isArray(arr)) {
|
|
14
|
-
console.error("第一个参数必须是一个数组。");
|
|
15
|
-
return [];
|
|
16
|
-
}
|
|
17
|
-
const validDirections = ['asc', 'desc'];
|
|
18
|
-
const validSortTypes = ['locale', 'natural'];
|
|
19
|
-
|
|
20
|
-
if (!validDirections.includes(direction) || !validSortTypes.includes(sortType)) {
|
|
21
|
-
console.error("排序方向或排序类型参数无效。");
|
|
22
|
-
return [...arr];
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
// 2. 创建数组副本
|
|
26
|
-
const sortedArr = arr.slice();
|
|
27
|
-
|
|
28
|
-
// 3. 定义类型处理和排序分组规则
|
|
29
|
-
// JavaScript 的 sort() 方法会将 undefined 和 null 移到末尾,
|
|
30
|
-
// 但为了确保排序稳定性和一致性,我们在这里显式处理它们。
|
|
31
|
-
const comparator = (a, b) => {
|
|
32
|
-
const isNullA = (a === null || typeof a === 'undefined');
|
|
33
|
-
const isNullB = (b === null || typeof b === 'undefined');
|
|
34
|
-
|
|
35
|
-
// 规则 A: 将 null/undefined 分组到末尾(默认行为)
|
|
36
|
-
if (isNullA && !isNullB) return 1;
|
|
37
|
-
if (!isNullA && isNullB) return -1;
|
|
38
|
-
if (isNullA && isNullB) return 0;
|
|
39
|
-
|
|
40
|
-
// 规则 B: 统一转换为字符串进行比较
|
|
41
|
-
// Date 对象会转为 ISO 字符串,Boolean 会转为 'true'/'false'
|
|
42
|
-
const strA = String(a);
|
|
43
|
-
const strB = String(b);
|
|
44
|
-
|
|
45
|
-
let comparison = 0;
|
|
46
|
-
|
|
47
|
-
// --- 内部比较逻辑 ---
|
|
48
|
-
if (sortType === 'locale') {
|
|
49
|
-
// 字典顺序
|
|
50
|
-
if (strA < strB) {
|
|
51
|
-
comparison = -1;
|
|
52
|
-
} else if (strA > strB) {
|
|
53
|
-
comparison = 1;
|
|
54
|
-
}
|
|
55
|
-
} else if (sortType === 'natural') {
|
|
56
|
-
// 自然顺序 (处理数字串和字母数字串)
|
|
57
|
-
comparison = strA.localeCompare(strB, undefined, { numeric: true, sensitivity: 'base' });
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// 4. 根据排序方向调整结果
|
|
61
|
-
return direction === 'asc' ? comparison : -comparison;
|
|
62
|
-
};
|
|
63
|
-
|
|
64
|
-
// 5. 执行排序
|
|
65
|
-
sortedArr.sort(comparator);
|
|
66
|
-
|
|
67
|
-
return sortedArr;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* 对一个由对象组成的数组进行多级排序。
|
|
72
|
-
*
|
|
73
|
-
* @param {Object[]} arr 待排序的对象数组。
|
|
74
|
-
* @param {Array<{field: string, direction: 'asc'|'desc', sortType: 'locale'|'natural'}>} sortRules 排序规则数组。
|
|
75
|
-
* - field: 用于排序的对象属性名称(字符串)。
|
|
76
|
-
* - direction: 排序方向,'asc'(升序)或 'desc'(降序)。
|
|
77
|
-
* - sortType: 排序类型,'locale'(字典/字母顺序)或 'natural'(自然顺序)。
|
|
78
|
-
* @returns {Object[]} 排序后的新数组。
|
|
79
|
-
*/
|
|
80
|
-
function sortObjectArrayMultiLevel(arr, sortRules) {
|
|
81
|
-
// 1. 参数校验
|
|
82
|
-
if (!Array.isArray(arr) || !Array.isArray(sortRules) || sortRules.length === 0) {
|
|
83
|
-
// 如果数组无效或规则为空,则返回数组副本
|
|
84
|
-
return [...arr];
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
// 2. 创建数组副本,以确保函数是纯函数(不修改原始数组)
|
|
88
|
-
const sortedArr = arr.slice();
|
|
89
|
-
|
|
90
|
-
// 3. 定义多级比较器
|
|
91
|
-
const multiLevelComparator = (a, b) => {
|
|
92
|
-
// 遍历所有排序规则,按顺序进行比较
|
|
93
|
-
for (const rule of sortRules) {
|
|
94
|
-
const { field, direction, sortType } = rule;
|
|
95
|
-
|
|
96
|
-
// 检查规则的有效性
|
|
97
|
-
if (!field || !['asc', 'desc'].includes(direction) || !['locale', 'natural'].includes(sortType)) {
|
|
98
|
-
console.warn(`跳过无效的排序规则: ${JSON.stringify(rule)}`);
|
|
99
|
-
continue; // 跳过当前规则,尝试下一个
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
// 获取待比较的字段值
|
|
103
|
-
const valA = a[field];
|
|
104
|
-
const valB = b[field];
|
|
105
|
-
|
|
106
|
-
let comparison = 0;
|
|
107
|
-
|
|
108
|
-
// --- 核心比较逻辑 ---
|
|
109
|
-
|
|
110
|
-
// 为了实现自然排序和字典排序的一致性,我们将值统一转换为字符串进行比较
|
|
111
|
-
const strA = String(valA);
|
|
112
|
-
const strB = String(valB);
|
|
113
|
-
|
|
114
|
-
if (sortType === 'locale') {
|
|
115
|
-
// 字典顺序 (Lexicographical Order)
|
|
116
|
-
if (strA < strB) {
|
|
117
|
-
comparison = -1;
|
|
118
|
-
} else if (strA > strB) {
|
|
119
|
-
comparison = 1;
|
|
120
|
-
}
|
|
121
|
-
} else if (sortType === 'natural') {
|
|
122
|
-
// 自然顺序 (Natural Sort Order)
|
|
123
|
-
// 使用 localeCompare 配合 { numeric: true } 选项
|
|
124
|
-
comparison = strA.localeCompare(strB, undefined, { numeric: true, sensitivity: 'base' });
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
// --- 调整排序结果并返回 ---
|
|
128
|
-
|
|
129
|
-
// 如果 comparison 不为 0,说明在当前字段上找到了差异,可以直接返回结果
|
|
130
|
-
if (comparison !== 0) {
|
|
131
|
-
// 根据排序方向调整比较结果
|
|
132
|
-
return direction === 'asc' ? comparison : -comparison;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
// 如果 comparison 为 0 (值相等),则继续循环,使用下一个规则进行比较
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
// 如果所有规则都比较完了,值仍然相等,则认为它们的相对顺序不重要
|
|
139
|
-
return 0;
|
|
140
|
-
};
|
|
141
|
-
|
|
142
|
-
// 4. 执行排序
|
|
143
|
-
sortedArr.sort(multiLevelComparator);
|
|
144
|
-
|
|
145
|
-
return sortedArr;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
/**
|
|
149
|
-
* 对一个由简单数据类型组成的数组进行去重。
|
|
150
|
-
* 使用 Set 对象,这是现代 JavaScript 中最推荐和最简洁的方法。
|
|
151
|
-
*
|
|
152
|
-
* @param {Array<any>} arr 待去重的数组(可包含数值、字符串、布尔值、null、undefined 等)。
|
|
153
|
-
* @returns {Array<any>} 包含唯一元素的新数组。
|
|
154
|
-
*/
|
|
155
|
-
const uniqueSimpleArray = (arr) => {
|
|
156
|
-
// 1. 检查输入是否为数组
|
|
157
|
-
if (!Array.isArray(arr)) {
|
|
158
|
-
console.error("输入必须是一个数组。");
|
|
159
|
-
return [];
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
// 2. 创建一个 Set 对象,Set 会自动过滤重复的值
|
|
163
|
-
// 3. 使用扩展运算符 (...) 将 Set 转换回数组
|
|
164
|
-
return [...new Set(arr)];
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
/**
|
|
168
|
-
* 对一个由对象组成的数组进行去重,根据多个指定的字段判断重复。
|
|
169
|
-
* 优化:在判断重复时,同时考虑字段的值和数据类型。
|
|
170
|
-
*
|
|
171
|
-
* @param {Object[]} arr 待去重的对象数组。
|
|
172
|
-
* @param {string[]} fields 用于判断重复的字段名数组。当所有指定字段的值和类型都相同时,视为重复。
|
|
173
|
-
* @returns {Object[]} 包含唯一元素的新数组,保留第一次出现的记录。
|
|
174
|
-
*/
|
|
175
|
-
function uniqueObjectArrayByFields(arr, fields) {
|
|
176
|
-
// 1. 参数校验
|
|
177
|
-
if (!Array.isArray(arr) || arr.length === 0) {
|
|
178
|
-
return [];
|
|
179
|
-
}
|
|
180
|
-
if (!Array.isArray(fields) || fields.length === 0) {
|
|
181
|
-
console.warn("未指定用于判断重复的字段,将返回原始数组副本。");
|
|
182
|
-
return [...arr];
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
// 用于存储已见过的唯一键
|
|
186
|
-
const seenKeys = new Set();
|
|
187
|
-
const uniqueArray = [];
|
|
188
|
-
const DELIMITER = "|||";
|
|
189
|
-
|
|
190
|
-
// 2. 遍历原始数组
|
|
191
|
-
for (const item of arr) {
|
|
192
|
-
// 3. 构建唯一键 (同时包含值和类型)
|
|
193
|
-
const keyParts = [];
|
|
194
|
-
|
|
195
|
-
for (const field of fields) {
|
|
196
|
-
const value = item[field];
|
|
197
|
-
const type = typeof value;
|
|
198
|
-
|
|
199
|
-
let valueString;
|
|
200
|
-
|
|
201
|
-
// 确保复杂类型(如对象、日期)也能被正确且唯一地表示
|
|
202
|
-
if (type === 'object' && value !== null) {
|
|
203
|
-
// 对于对象/数组/日期,使用 JSON 序列化
|
|
204
|
-
valueString = JSON.stringify(value);
|
|
205
|
-
} else if (type === 'undefined' || value === null) {
|
|
206
|
-
// 明确区分 undefined 和 null
|
|
207
|
-
valueString = String(value);
|
|
208
|
-
} else {
|
|
209
|
-
// 对于简单类型(string, number, boolean),直接转换为字符串
|
|
210
|
-
valueString = String(value);
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
// 键结构: [值字符串] + [DELIMITER] + [数据类型]
|
|
214
|
-
// 例如: '1|||number' 或 '1|||string'
|
|
215
|
-
keyParts.push(valueString + DELIMITER + type);
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
// 最终键由所有字段的键结构连接而成
|
|
219
|
-
const uniqueKey = keyParts.join(DELIMITER);
|
|
220
|
-
|
|
221
|
-
// 4. 检查是否重复
|
|
222
|
-
if (!seenKeys.has(uniqueKey)) {
|
|
223
|
-
// 如果这个键是第一次出现,则保留
|
|
224
|
-
seenKeys.add(uniqueKey);
|
|
225
|
-
uniqueArray.push(item);
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
return uniqueArray;
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
export {
|
|
233
|
-
sortSimpleArray,
|
|
234
|
-
sortObjectArrayMultiLevel,
|
|
235
|
-
uniqueSimpleArray,
|
|
236
|
-
uniqueObjectArrayByFields
|
|
237
|
-
}
|
|
238
|
-
export default {
|
|
239
|
-
sortSimpleArray,
|
|
240
|
-
sortObjectArrayMultiLevel,
|
|
241
|
-
uniqueSimpleArray,
|
|
242
|
-
uniqueObjectArrayByFields
|
|
243
|
-
}
|