我遇到了这个用例,但对此感到困惑:
const naturalCollator = new Intl.Collator(undefined, {
numeric: true,
sensitivity: 'base'
});
const comparator = (a, b) => naturalCollator.compare(a, b);
const numbers = [-1, 0, 1, 10, NaN, 2, -0.001, NaN, 0, -1, -Infinity, NaN, 5, -10, Infinity, 0];
console.log(numbers.sort(comparator));
结果数组以降序排列负数,而以升序排列正数。例如:
[-3, 1, -2, 2].sort(comparator)
// [-2, -3, 1, 2]
自 Intl.Collator是“语言敏感的字符串比较”,它是否简单地忽略符号并且只将每个数字评估为正数?
编辑
另一个不一致是这个:
["b1", "a-1", "b-1", "a+1", "a1"].sort(comparator);
// ['a-1', 'a+1', 'a1', 'b-1', 'b1']
在哪里'a' < 'b'
所以顺序没问题,但是'-' > '+'
那为什么是"a-1"
之前 "a+1"
?
换句话说,无论字符代码如何,负号都被认为小于正号,但是"-1"
被认为小于 "-2"
, 忽略标志。
最佳答案
默认的字符串排序算法使用被比较字符串中每个代码单元的 unicode 值。这称为“词典排序”。
当您设置整理器选项时,您正在定义对此行为的特定覆盖(您可以将它们视为比字典排序更高优先级的规则)。
这是相关规范部分的链接:https://tc39.es/ecma402/#sec-collator-comparestrings
比较数字值时(如您的示例),第一步是将数字强制转换为字符串,然后再用于内部排序函数。
使用 numeric
时选项,效果仅适用于分类为数字的代码单元。
在字符串化负值的情况下,连字符被评估为非数字字符。然后将连续的数字序列评估为类似数字的组。
在对以连字符和数字开头的其他字符串进行排序时,您可以看到这种效果:
const opts = { numeric: true, sensitivity: 'base' };
const naturalCollator = new Intl.Collator(undefined, opts);
const values = [-3, 1, -2, 2, '-foo', '-bar', 'foo', 'bar'];
console.log(values.sort(naturalCollator.compare));
//=> [-2, -3, "-bar", "-foo", 1, 2, "bar", "foo"]
numeric
选项有用的另一个例子:考虑一系列带有数字子字符串的文件名,用于分组排序:
const opts = { numeric: true, sensitivity: 'base' };
const naturalCollator = new Intl.Collator(undefined, opts);
const fileNames = [
'IMG_1.jpg',
'IMG_2.jpg',
'IMG_3.jpg',
// ...
'IMG_100.jpg',
'IMG_101.jpg',
'IMG_102.jpg',
// ...
'IMG_200.jpg',
'IMG_201.jpg',
'IMG_202.jpg',
// etc...
];
fileNames.sort();
console.log(fileNames); // 🙈
//=> ["IMG_1.jpg", "IMG_100.jpg", "IMG_101.jpg", "IMG_102.jpg", "IMG_2.jpg", "IMG_200.jpg", "IMG_201.jpg", "IMG_202.jpg", "IMG_3.jpg"]
fileNames.sort(naturalCollator.compare);
console.log(fileNames); // 🤩
//=> ["IMG_1.jpg", "IMG_2.jpg", "IMG_3.jpg", "IMG_100.jpg", "IMG_101.jpg", "IMG_102.jpg", "IMG_200.jpg", "IMG_201.jpg", "IMG_202.jpg"]
关于javascript - 为什么 Intl.Collator 对负数进行降序排序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73939121/