You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在JavaScript中对字符串+数字混合路径数组进行自然排序?

需求:对含数字的层级路径数组进行自然排序

示例输入

['/catalog/tag/categories/0', 
'/catalog/tag/categories/0/categories/0', 
'/catalog/tag/categories/0/categories/1', 
'/catalog/tag/categories/1', 
'/catalog/tag/categories/1/categories/0', 
'/catalog/tag/categories/1/categories/1', 
'/catalog/tag/categories/2', 
'/catalog/tag/categories/2/categories/0', 
'/catalog/tag/categories/2/categories/1', 
'/catalog/tag/categories/2/categories/10', 
'/catalog/tag/categories/2/categories/11', 
'/catalog/tag/categories/2/categories/14', 
'/catalog/tag/categories/2/categories/15', 
'/catalog/tag/categories/2/categories/16', 
'/catalog/tag/categories/2/categories/17', 
'/catalog/tag/categories/2/categories/2', 
'/catalog/tag/categories/2/categories/3', 
'/catalog/tag/categories/2/categories/7', 
'/catalog/tag/categories/2/categories/8', 
'/catalog/tag/categories/2/categories/9'];

期望输出

['/catalog/tag/categories/0', 
'/catalog/tag/categories/0/categories/0', 
'/catalog/tag/categories/0/categories/1', 
'/catalog/tag/categories/1', 
'/catalog/tag/categories/1/categories/0', 
'/catalog/tag/categories/1/categories/1', 
'/catalog/tag/categories/2', 
'/catalog/tag/categories/2/categories/0', 
'/catalog/tag/categories/2/categories/1', 
'/catalog/tag/categories/2/categories/2', 
'/catalog/tag/categories/2/categories/3', 
'/catalog/tag/categories/2/categories/7', 
'/catalog/tag/categories/2/categories/8', 
'/catalog/tag/categories/2/categories/9',
'/catalog/tag/categories/2/categories/10', 
'/catalog/tag/categories/2/categories/11', 
'/catalog/tag/categories/2/categories/14', 
'/catalog/tag/categories/2/categories/15', 
'/catalog/tag/categories/2/categories/16', 
'/catalog/tag/categories/2/categories/17'];

Python可行实现

已通过以下Python代码实现需求:

import re

def natural_sort(l):
   convert = lambda text: int(text) if text.isdigit() else text.lower()
   alphanum_key = lambda key: [convert(c) for c in re.split('([0-9]+)', key)]
   print(sorted(l, key=alphanum_key))

尝试的JavaScript代码(不符合预期)

以下JS代码排序结果不符合要求,会将同前缀的子路径排在父路径之后:

var reA = /[^a-zA-Z]/g;
var reN = /[^0-9]/g;

function sortAlphaNum(a, b) {
  var aA = a.replace(reA, "");
  var bA = b.replace(reA, "");
  if (aA === bA) {
    var aN = parseInt(a.replace(reN, ""), 10);
    var bN = parseInt(b.replace(reN, ""), 10);
    return aN === bN ? 0 : aN > bN ? 1 : -1;
  } else {
    return aA > bA ? 1 : -1;
  }
}

console.log(arr.sort(sortAlphaNum));

错误输出结果

['/catalog/tag/categories/0', 
'/catalog/tag/categories/1', 
'/catalog/tag/categories/2', 
'/catalog/tag/categories/0/categories/0', 
'/catalog/tag/categories/0/categories/1', 
'/catalog/tag/categories/1/categories/0', 
'/catalog/tag/categories/1/categories/1', 
'/catalog/tag/categories/2/categories/0', 
'/catalog/tag/categories/2/categories/1', 
'/catalog/tag/categories/2/categories/2', 
'/catalog/tag/categories/2/categories/3', 
'/catalog/tag/categories/2/categories/7', 
'/catalog/tag/categories/2/categories/8', 
'/catalog/tag/categories/2/categories/9',
'/catalog/tag/categories/2/categories/10', 
'/catalog/tag/categories/2/categories/11', 
'/catalog/tag/categories/2/categories/14', 
'/catalog/tag/categories/2/categories/15', 
'/catalog/tag/categories/2/categories/16', 
'/catalog/tag/categories/2/categories/17'];

正确的JavaScript实现方案

借鉴Python的思路,实现支持任意层级路径的自然排序,同时保证父路径优先于子路径:

实现代码

function naturalSortPaths(arr) {
  // 转换函数:数字字符串转整数,其他转小写
  const convert = text => text.match(/^\d+$/) ? parseInt(text, 10) : text.toLowerCase();
  
  // 生成排序键:将路径按数字和非数字拆分,转换后得到数组
  const getSortKey = path => path.split(/(\d+)/).map(convert);
  
  return arr.sort((a, b) => {
    const keyA = getSortKey(a);
    const keyB = getSortKey(b);
    
    // 逐段比较路径片段
    for (let i = 0; i < Math.min(keyA.length, keyB.length); i++) {
      if (keyA[i] !== keyB[i]) {
        // 数字按大小比较,字符串按自然顺序比较
        return typeof keyA[i] === 'number' 
          ? keyA[i] - keyB[i] 
          : keyA[i].localeCompare(keyB[i]);
      }
    }
    
    // 前缀完全相同时,短路径(父路径)排在前面
    return keyA.length - keyB.length;
  });
}

// 测试示例
const arr = ['/catalog/tag/categories/0', 
'/catalog/tag/categories/0/categories/0', 
'/catalog/tag/categories/0/categories/1', 
'/catalog/tag/categories/1', 
'/catalog/tag/categories/1/categories/0', 
'/catalog/tag/categories/1/categories/1', 
'/catalog/tag/categories/2', 
'/catalog/tag/categories/2/categories/0', 
'/catalog/tag/categories/2/categories/1', 
'/catalog/tag/categories/2/categories/10', 
'/catalog/tag/categories/2/categories/11', 
'/catalog/tag/categories/2/categories/14', 
'/catalog/tag/categories/2/categories/15', 
'/catalog/tag/categories/2/categories/16', 
'/catalog/tag/categories/2/categories/17', 
'/catalog/tag/categories/2/categories/2', 
'/catalog/tag/categories/2/categories/3', 
'/catalog/tag/categories/2/categories/7', 
'/catalog/tag/categories/2/categories/8', 
'/catalog/tag/categories/2/categories/9'];

console.log(naturalSortPaths(arr));

代码说明

  1. convert函数:统一处理路径片段,数字转整数保证数值排序,非数字转小写保证大小写不敏感排序。
  2. getSortKey函数:用正则/(\d+)/拆分路径,将每个数字和非数字部分单独提取,生成排序用的键数组。
  3. 排序逻辑:
    • 逐段对比两个路径的键数组,数字直接比较大小,字符串用localeCompare实现自然排序。
    • 若前缀完全一致,短路径(父路径)优先于长路径(子路径),满足层级排序需求。

内容的提问来源于stack exchange,提问作者cfwithdecaf

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 05:15:35