Skip to content

Commit 1e34aef

Browse files
committed
optimize name sort logic
1 parent ada8fd9 commit 1e34aef

2 files changed

Lines changed: 71 additions & 24 deletions

File tree

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"private": true,
33
"type": "module",
4-
"version": "1.0.7",
4+
"version": "1.0.8",
55
"scripts": {
66
"dev": "vite",
77
"build": "vite build",

src/utils/CommonUtils.jsx

Lines changed: 70 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -169,16 +169,6 @@ export function getParentPath(path = getRoutePath()) {
169169
}
170170

171171

172-
function extractNumber(str, start) {
173-
let result = 0;
174-
let i = start;
175-
while (i < str.length && /\d/.test(str[i])) {
176-
result = result * 10 + (str.charCodeAt(i) - 48);
177-
i++;
178-
}
179-
return result;
180-
}
181-
182172
export function deepEqual(a, b) {
183173
// 基本类型和引用类型直接比较
184174
if (a === b) return true;
@@ -199,21 +189,78 @@ export function deepEqual(a, b) {
199189
return aKeys.every(key => b.hasOwnProperty(key) && deepEqual(a[key], b[key]));
200190
}
201191

192+
/**
193+
* 优化后的 Windows 文件名自然排序算法
194+
*/
202195
export function compareByName(a, b) {
203-
let i1 = 0, i2 = 0;
204-
while (i1 < a.length && i2 < b.length) {
205-
if (/\d/.test(a[i1]) && /\d/.test(b[i2])) {
206-
const n1 = extractNumber(a, i1);
207-
const n2 = extractNumber(b, i2);
208-
i1 += n1.toString().length;
209-
i2 += n2.toString().length;
210-
if (n1 !== n2) return n1 - n2;
196+
if (a === b) return 0;
197+
198+
const len1 = a.length;
199+
const len2 = b.length;
200+
let i = 0;
201+
let j = 0;
202+
203+
while (i < len1 && j < len2) {
204+
let c1 = a.charCodeAt(i);
205+
let c2 = b.charCodeAt(j);
206+
207+
// 判断是否为数字 (0-9)
208+
const isDig1 = c1 >= 48 && c1 <= 57;
209+
const isDig2 = c2 >= 48 && c2 <= 57;
210+
211+
if (isDig1 && isDig2) {
212+
let start1 = i;
213+
let start2 = j;
214+
215+
// 跳过前导零,但保留最后一个零(如果是全零的情况)
216+
while (i < len1 - 1 && a.charCodeAt(i) === 48) {
217+
const next = a.charCodeAt(i + 1);
218+
if (next < 48 || next > 57) break;
219+
i++;
220+
}
221+
while (j < len2 - 1 && b.charCodeAt(j) === 48) {
222+
const next = b.charCodeAt(j + 1);
223+
if (next < 48 || next > 57) break;
224+
j++;
225+
}
226+
227+
let valStart1 = i;
228+
let valStart2 = j;
229+
230+
while (i < len1 && (c1 = a.charCodeAt(i)) >= 48 && c1 <= 57) i++;
231+
while (j < len2 && (c2 = b.charCodeAt(j)) >= 48 && c2 <= 57) j++;
232+
233+
const numLen1 = i - valStart1;
234+
const numLen2 = j - valStart2;
235+
236+
// 长度不同,数值大的字符串肯定长
237+
if (numLen1 !== numLen2) return numLen1 - numLen2;
238+
239+
// 长度相同,逐位比较
240+
for (let k = 0; k < numLen1; k++) {
241+
const diff = a.charCodeAt(valStart1 + k) - b.charCodeAt(valStart2 + k);
242+
if (diff !== 0) return diff;
243+
}
244+
245+
// 数值完全一样,比较含前导零的原始长度 (短的在前)
246+
const fullLen1 = i - start1;
247+
const fullLen2 = j - start2;
248+
if (fullLen1 !== fullLen2) return fullLen1 - fullLen2;
249+
211250
} else {
212-
if (a[i1] !== b[i2]) return a[i1].charCodeAt(0) - b[i2].charCodeAt(0);
213-
i1++;
214-
i2++;
251+
if (c1 !== c2) {
252+
// 转小写比较 (仅限 A-Z)
253+
const low1 = (c1 >= 65 && c1 <= 90) ? c1 + 32 : c1;
254+
const low2 = (c2 >= 65 && c2 <= 90) ? c2 + 32 : c2;
255+
256+
if (low1 !== low2) return low1 - low2;
257+
// 如果小写相同但原始码点不同(如 'a' vs 'A'),保持稳定排序
258+
return c1 - c2;
259+
}
260+
i++;
261+
j++;
215262
}
216263
}
217-
return a.length - b.length;
218-
}
219264

265+
return len1 - len2;
266+
}

0 commit comments

Comments
 (0)