如何按文件名中嵌入的数字对字符串数组进行自然排序

14次阅读

如何按文件名中嵌入的数字对字符串数组进行自然排序

本文讲解如何使用 javascript 的 `sort()` 方法,结合正则提取与数值比较,对包含递增数字后缀的文件名数组进行正确升序排序,解决默认字符串排序导致的 `13810` 错排在 `1386` 之前的 常见问题

JavaScript 中原生的 Array.prototype.sort() 默认按字符串 Unicode 码点排序,而非数值大小。因此,当文件名如 “IMG_COM_…_13810.webp” 与 “IMG_COM_…_1386.webp” 混合时,字符串比较会先比 ‘1381’

要实现 按末尾数字部分的数值大小升序 排列(即自然排序),需提供自定义比较函数,并准确提取该数字。观察示例数据:

const img = ["IMG_COM_20220516_1150_41_1375.webp",   "IMG_COM_20220516_1150_41_13810.webp",   "IMG_COM_20220516_1150_41_1386.webp",   // ……];

所有文件名均以 _ 分隔,数字位于倒数第一段(_.webp 前),因此可采用两种稳健提取方式:

推荐:正则提取(更健壮)
使用 /d+(?=.w+$)/ 匹配最后一个点号前的连续数字:

img.sort((a, b) => {const numA = parseInt(a.match(/d+(?=.w+$)/)[0], 10);   const numB = parseInt(b.match(/d+(?=.w+$)/)[0], 10);   return numA - numB; // 升序;若需降序,改为 `numB - numA` });

备选:字符串分割(适用于固定格式)
如确认数字总在最后一段下划线后、扩展名前,也可用:

img.sort((a, b) => {const numA = parseInt(a.split('_').slice(-1)[0].split('.')[0], 10);   const numB = parseInt(b.split('_').slice(-1)[0].split('.')[0], 10);   return numA - numB; });

⚠️ 注意事项:必须使用 parseInt(…, 10) 明确指定十进制,避免八进制解析风险;正则方案对文件名格式变化(如多级子目录、不同分隔符)更具鲁棒性;若存在无法匹配数字的项,建议增加空值防护:?.[0] || ‘0’;sort() 是原地排序,会直接修改原数组;如需保留原始顺序,请先 .slice() 或 […arr] 浅拷贝。

执行后,输出完全符合预期:

["IMG_COM_20220516_1150_41_1375.webp",   "IMG_COM_20220516_1150_41_1386.webp",   "IMG_COM_20220516_1150_41_1389.webp",   "IMG_COM_20220516_1150_41_13810.webp",   "IMG_COM_20220516_1150_41_13911.webp",   "IMG_COM_20220516_1150_41_13912.webp"]

掌握这种“提取—转换—比较”模式,即可灵活应对各类基于内嵌数值的字符串排序需求。

text=ZqhQzanResources