KernelRanch
返回文章列表

文件列表为什么把 10 排在 2 前面:用 Intl.Collator 定义排序

2026-11-13 #javascript#i18n#sorting

文件列表里的 file-10 排在 file-2 前面,通常是因为使用了默认字符串排序。数字片段可用 Intl.Collator 的 numeric 选项比较。人名或目录标题还要显式选择语言,因为不同语言对同一字母的排序规则可能不同。

1. 本机复现

保存为 collation_lab.mjs,运行 node collation_lab.mjs。样本包含数字文件名、带变音符的字母,以及主排序规则下等价的两个标签。

import assert from 'node:assert/strict';

const names = ['file-2', 'file-10', 'file-1'];
const natural = new Intl.Collator('en', { numeric: true });
const plain = [...names].sort();
const numeric = [...names].sort(natural.compare);
assert.deepEqual(plain, ['file-1', 'file-10', 'file-2']);
assert.deepEqual(numeric, ['file-1', 'file-2', 'file-10']);
console.log('default:', plain.join(', '));
console.log('numeric:', numeric.join(', '));

for (const [locale, expected] of [
  ['de', ['a', 'ä', 'z']],
  ['sv', ['a', 'z', 'ä']],
]) {
  const collator = new Intl.Collator(locale);
  const letters = ['z', 'ä', 'a'].sort(collator.compare);
  assert.deepEqual(letters, expected);
  console.log(locale + ':', letters.join(', '));
}

const byLabel = new Intl.Collator('en', { sensitivity: 'base' });
const items = [{ id: 7, label: 'alpha' }, { id: 2, label: 'Alpha' }];
assert.equal(byLabel.compare(items[0].label, items[1].label), 0);
items.sort((a, b) => byLabel.compare(a.label, b.label) || a.id - b.id);
assert.deepEqual(items.map(item => item.id), [2, 7]);
console.log('equal labels, ID order:', items.map(item => item.id).join(', '));

本地实测输出如下。

default: file-1, file-10, file-2
numeric: file-1, file-2, file-10
de: a, ä, z
sv: a, z, ä
equal labels, ID order: 2, 7

2. 让显示顺序与分页顺序一致

默认排序把字符串按 UTF-16 代码单元顺序比较。Intl.Collator 会根据生效的语言和选项比较,调用方只应依赖返回值的正负或零。numeric: true 适合文件名等数字片段,语义化版本应使用理解主版本、预发布字段等规则的比较器。

展示层可以按用户语言复用已创建的 Collator。服务端分页时应先对完整结果按统一规则排序,再取一页。浏览器拿到一页后自行重排,只能改变这一页的内部次序。主键等唯一字段可以为比较结果为零的记录补上确定顺序。对跨环境要求完全一致的排序,还要固定参与排序的语言数据和版本。

小结

给数字片段和本地化文本选定比较规则。分页使用同一排序规则和唯一的次级键。

数据来源与检索时间

检索时间 2026-11-13。

来源URL对应内容
ECMA-262 Array.prototype.sorthttps://tc39.es/ecma262/#sec-array.prototype.sort默认比较与排序行为
ECMA-402 Intl.Collatorhttps://tc39.es/ecma402/#collator-objects语言、数字选项、比较结果及版本差异

核验说明

  • Windows、Node.js v24.19.0 验证数字文件名、德语与瑞典语顺序,以及标签相等时按 ID 排序。观测结果基于该运行时的国际化数据。