← 中文资源

简体中文版本

自然排序:数字按数值比较

借助 Intl.Collator 让 item2 排在 item10 之前,并用确定性平局规则保证跨引擎结果稳定。

阅读英文原文

功能说明

naturalSort 按人类阅读习惯排序文件名、版本标签、表格列名等文本,使 item2 排在 item10 之前,而不是按字符编码得到 item10 在前的顺序。createNaturalComparator 允许指定语言与 Intl.Collator 选项,默认忽略大小写和重音差异。naturalSort 返回新数组,不修改调用方数据,适合表格排序、文件列表和目录树展示。

关键代码

比较器由 Intl.Collator 驱动,开启 numeric 后连续数字会按数值比较,sensitivity 设为 base 让大小写与重音不参与主排序。collator.compare 返回零时,代码再用字符串的小于比较做平局判定,确保不同运行时对等价字符串仍给出稳定顺序,避免排序结果抖动。工厂函数把 collator 提升到闭包外,批量排序时无需反复创建。

使用注意

numeric 只识别连续数字,小数点和负号仍按普通字符处理,若要排序带符号小数应先解析成数值。不同 locale 的排序习惯不同,面向国际用户时应传入明确语言而不是依赖运行环境默认值。忽略大小写意味着 A 与 a 的比较结果为零,若业务要求大写优先需额外传入 caseFirst 选项。排序稳定性还依赖底层 sort,现代引擎已保证稳定。

验证方式

用包含 item1、item2、item10 的数组断言自然顺序,并测试纯数字字符串、带前导零的编号与混合中英文标签。构造大小写不同但 collator 判定相等的值,确认平局规则给出确定顺序。再测试空数组、单元素、非数组输入,以及传入自定义 locale 和 caseFirst 选项时的结果差异。

代码示例

export function createNaturalComparator(locale = "en", options = {}) {
  const collator = new Intl.Collator(locale, {
    numeric: true,
    sensitivity: "base",
    ...options,
  });
  return (left, right) => {
    const a = String(left);
    const b = String(right);
    return collator.compare(a, b) || (a < b ? -1 : a > b ? 1 : 0);
  };
}

export const naturalCompare = createNaturalComparator();

export function naturalSort(values, compare = naturalCompare) {
  if (!Array.isArray(values)) throw new TypeError("values must be an array");
  return [...values].sort(compare);
}