如何控制排序时大写或小写字母的优先级
使用 Intl.Collator 中的 caseFirst 选项来确定字符串排序时的大小写顺序
介绍
当您对仅在大小写上有所不同的字符串数组进行排序时,JavaScript 需要决定哪个版本排在前面。是 apple 应该排在 Apple 之前,还是 Apple 应该排在 apple 之前?不同的应用程序对这种排序有不同的要求。
默认情况下,仅在大小写上不同的字符串的排序顺序取决于语言环境和敏感度设置。在许多情况下,像 apple 和 Apple 这样的字符串被视为相等,从而使它们的顺序不可预测。如果您的应用程序对大小写排序有要求,则需要明确控制是大写字母还是小写字母排在前面。
Intl.Collator API 提供了一个 caseFirst 选项,用于确定大小写排序。您可以配置排序器将大写字母排在小写字母之前、小写字母排在大写字母之前,或者使用语言环境的默认行为。本课程将解释 caseFirst 选项的工作原理、其影响范围以及如何在实际排序场景中使用它。
caseFirst 选项的作用
caseFirst 选项控制仅在大小写上有所不同的字符串的排序顺序。它接受三个字符串值:"upper"、"lower" 或 "false"。
当设置为 "upper" 时,大写字母排在其小写字母等价物之前。字符串 Apple 排在 apple 之前。
当设置为 "lower" 时,小写字母排在其大写字母等价物之前。字符串 apple 排在 Apple 之前。
当设置为 "false"(字符串值,而非布尔值)时,排序器使用语言环境的默认大小写排序。这是未指定选项时的默认行为。
caseFirst 选项仅影响仅在大小写上不同的字符串。无论此设置如何,基础字母不同的字符串仍然按照正常的字母顺序规则排序。
默认大小写排序的工作原理
如果未指定 caseFirst 选项,排序器会使用取决于语言环境和敏感度设置的默认行为。
const collator = new Intl.Collator('en-US');
const words = ['apple', 'Apple', 'APPLE'];
words.sort(collator.compare);
console.log(words);
// 输出: ['apple', 'Apple', 'APPLE']
输出顺序取决于实现和语言环境。在默认敏感度设置下,排序器会考虑大小写差异,但 apple、Apple 和 APPLE 的具体排序可能会有所不同。
不同的语言环境有不同的默认大小写排序约定。一些语言环境通常将小写字母放在前面,而另一些则将大写字母放在前面。依赖默认行为会导致在不同环境中产生不一致的结果。
使用 caseFirst upper 将大写字母放在前面
设置 caseFirst: "upper" 可确保大写字母在排序结果中始终位于其小写字母之前。
const collator = new Intl.Collator('en-US', { caseFirst: 'upper' });
const words = ['apple', 'Apple', 'banana', 'Banana'];
words.sort(collator.compare);
console.log(words);
// 输出: ['Apple', 'apple', 'Banana', 'banana']
排序器首先按字母的基本字母顺序排序,然后在每组内应用大小写排序。在以 a 开头的单词中,Apple 位于 apple 之前。在以 b 开头的单词中,Banana 位于 banana 之前。
这种排序在显示列表时非常有用,例如需要将专有名词或大写标题显著地放在普通名词之前。
const collator = new Intl.Collator('en-US', { caseFirst: 'upper' });
const names = ['smith', 'Smith', 'jones', 'Jones'];
names.sort(collator.compare);
console.log(names);
// 输出: ['Jones', 'jones', 'Smith', 'smith']
大写的名字会出现在小写版本之前,这使得在混合列表中区分专有名词和普通单词更加容易。
使用 caseFirst lower 将小写字母放在前面
设置 caseFirst: "lower" 确保在排序结果中,小写字母始终位于其大写字母等价项之前。
const collator = new Intl.Collator('en-US', { caseFirst: 'lower' });
const words = ['apple', 'Apple', 'banana', 'Banana'];
words.sort(collator.compare);
console.log(words);
// 输出: ['apple', 'Apple', 'banana', 'Banana']
排序器首先按字母顺序排序,然后在每个字母组内将小写版本放在大写版本之前。
这种排序方式符合小写文本被认为更标准或中性的惯例,而大写通常用于强调或特殊情况。
const collator = new Intl.Collator('en-US', { caseFirst: 'lower' });
const tags = ['javascript', 'JavaScript', 'python', 'Python'];
tags.sort(collator.compare);
console.log(tags);
// 输出: ['javascript', 'JavaScript', 'python', 'Python']
小写标签优先出现,这在小写表示规范形式而大写版本是较少见的变体时非常有用。
使用 caseFirst: "false" 以启用区域设置的默认行为
设置 caseFirst: "false"(字符串值)明确请求使用区域设置的默认大小写排序。这与完全省略该选项的结果相同。
const collator = new Intl.Collator('en-US', { caseFirst: 'false' });
const words = ['apple', 'Apple', 'APPLE'];
words.sort(collator.compare);
console.log(words);
// 输出取决于区域设置的实现
输出顺序取决于区域设置认为的标准。一些区域设置定义大写优先,另一些定义小写优先,还有一些将大小写不同的字符串视为相等。
当您希望明确表示使用区域设置默认值而不是意外省略配置选项时,此选项非常有用。
当 caseFirst 无效时
caseFirst 选项仅在敏感度设置允许大小写差异起作用时才会影响比较。当使用 sensitivity: "base" 或 sensitivity: "accent" 时,大小写差异完全被忽略,因此 caseFirst 选项无关紧要。
const collator = new Intl.Collator('en-US', {
sensitivity: 'base',
caseFirst: 'upper'
});
const words = ['apple', 'Apple', 'APPLE'];
words.sort(collator.compare);
console.log(words);
// 输出: ['apple', 'Apple', 'APPLE'](或任意顺序)
在基本敏感度下,排序器将这三个字符串视为相等。由于大小写不被考虑,caseFirst 选项不起作用。排序算法保留了相等项的原始顺序(稳定排序),因此输出与输入顺序一致。
要使 caseFirst 生效,请使用 sensitivity: "case" 或 sensitivity: "variant"(默认值)。
const collator = new Intl.Collator('en-US', {
sensitivity: 'variant',
caseFirst: 'upper'
});
const words = ['apple', 'Apple', 'APPLE'];
words.sort(collator.compare);
console.log(words);
// 输出: ['APPLE', 'Apple', 'apple']
在变体敏感度下(考虑所有差异,包括大小写),caseFirst 选项决定了这些大小写不同字符串的排序顺序。
使用一致的大小写排序名称
在对用户名或其他专有名词进行排序时,一致的大小写排序可以确保您的应用程序中获得可预测的结果。
const collator = new Intl.Collator('en-US', { caseFirst: 'upper' });
const users = [
{ name: 'alice' },
{ name: 'Alice' },
{ name: 'bob' },
{ name: 'Bob' }
];
users.sort((a, b) => collator.compare(a.name, b.name));
users.forEach(user => {
console.log(user.name);
});
// 输出:
// Alice
// alice
// Bob
// bob
排序器会将大写名称放在小写版本之前。这种排序方式使在混合数据集中区分专有名词和普通单词变得更加容易。
使用受控大小写顺序排序文件名
文件系统对大小写的敏感性行为各不相同。有些将大写和小写视为相同,有些则将它们视为不同。显式的大小写排序可以确保您的文件列表排序符合用户期望,而不受底层文件系统的影响。
const collator = new Intl.Collator('en-US', { caseFirst: 'lower' });
const files = ['README.md', 'readme.md', 'index.js', 'Index.js'];
files.sort(collator.compare);
console.log(files);
// 输出:['index.js', 'Index.js', 'readme.md', 'README.md']
小写版本会优先出现,这符合在类 Unix 系统中小写文件名更为常见的惯例。
将 caseFirst 与数字排序结合使用
caseFirst 选项可以与其他排序选项(如 numeric)一起使用。您可以在控制大小写排序的同时对包含数字的字符串进行排序。
const collator = new Intl.Collator('en-US', {
numeric: true,
caseFirst: 'upper'
});
const items = ['item1', 'Item1', 'item2', 'Item2', 'item10', 'Item10'];
items.sort(collator.compare);
console.log(items);
// 输出:['Item1', 'item1', 'Item2', 'item2', 'Item10', 'item10']
排序器对数字部分应用数字比较,对字母部分应用大小写排序。项目首先按数字值排序(1、2、10),然后在每个数字组内按大小写排序。
使用 Unicode 扩展键设置 caseFirst
caseFirst 选项也可以通过在区域标识符中使用 kf 键的 Unicode 扩展来设置。扩展值包括 upper、lower 和 false。
const collator = new Intl.Collator('en-US-u-kf-upper');
const words = ['apple', 'Apple', 'banana', 'Banana'];
words.sort(collator.compare);
console.log(words);
// 输出: ['Apple', 'apple', 'Banana', 'banana']
区域字符串 en-US-u-kf-upper 指定了美式英语,并使用大写优先的排序规则。这与在选项对象中传递 { caseFirst: 'upper' } 产生相同的结果。
当 Unicode 扩展和选项对象同时指定 caseFirst 时,选项对象优先。
const collator = new Intl.Collator('en-US-u-kf-upper', {
caseFirst: 'lower'
});
const words = ['apple', 'Apple'];
words.sort(collator.compare);
console.log(words);
// 输出: ['apple', 'Apple']
选项对象指定了 caseFirst: 'lower',覆盖了区域字符串中的 kf-upper 扩展。比较器使用小写优先的排序规则。
检查比较器使用的 caseFirst 值
resolvedOptions() 方法返回比较器实际使用的选项,包括 caseFirst 设置。
const collator = new Intl.Collator('en-US', { caseFirst: 'upper' });
const options = collator.resolvedOptions();
console.log(options.caseFirst);
// 输出: "upper"
这对于调试或验证比较器是否具有预期配置非常有用,尤其是在结合 Unicode 扩展和选项对象时。
const collator = new Intl.Collator('en-US-u-kf-lower');
const options = collator.resolvedOptions();
console.log(options.caseFirst);
// 输出: "lower"
当没有选项对象覆盖时,解析的选项反映了 Unicode 扩展设置。
何时使用每种 caseFirst 值
在以下情况下使用 caseFirst: "upper":
- 您希望专有名词或标题出现在普通单词之前
- 您的应用程序约定将大写文本视为更重要
- 您正在对名称进行排序,其中大写版本是规范形式
在以下情况下使用 caseFirst: "lower":
- 您希望小写文本作为标准形式出现在前面
- 您的应用程序约定将小写视为默认,大写视为特殊
- 您正在对技术标识符进行排序,其中小写更为常见
在以下情况下使用 caseFirst: "false":
- 您希望遵循特定区域的约定
- 对于您的应用程序,区分大小写的字符串顺序无关紧要
- 您希望明确表示使用默认值,而不是意外省略选项