其中数据是以下格式的元数组,
[
[
"qux doo",
"adsf",
"abcd",
"zzzz",
"898jwe9"
],
[
"abcd",
"xxrwu",
"urnr",
"pupupu",
"sdsdsd"
]
]
对于不同的输入数据值,以下两种算法是否会产生不同的结果?
data.sort(function(a,b){
return (JSON.stringify(a) < JSON.stringify(b)) - (JSON.stringify(a) > JSON.stringify(b));
});
data.sort(function(a, b) {
for (var i = 0; i < Math.min(a.length, b.length); i++) {
if (a[i] < b[i]) return -1;
if (a[i] > b[i]) return 1;
}
return (a.length > b.length) - (a.length < b.length);
});
最佳答案
JSON.stringify()
将转义某些字符(如双引号字符、反斜杠字符或任何控制字符),因此这些字符不太可能正确排序。
此外,由于空格的 ascii 码比双引号低,如果您的两个数组以 "abcd "
和 "abcd"
开头,它们不会在 JSON 中正确排序。 "abcd "
应该在 "abcd"
之后,但是空格的 ascii 值比双引号低,所以它会排在前面。对于值末尾的感叹号也是如此。
如果根据您的评论,您还希望它适用于非数组成员,例如数字,则字符串比较不适用于比较具有不同位数的两个数字,因为 1000
不少于小于 2
,但 "1000"
小于 "2"
。
此外,我建议您在第二个算法中使用 .localeCompare()
比较两个字符串,因为它已经具有内置的正、负或零结果。
如果您所有的值都是字符串或者它们通过 .toString()
正确排序,您可以像这样使用 .localeCompare()
:
data.sort(function(a, b) {
var comp, i;
for (i = 0; i < Math.min(a.length, b.length); i++) {
if ((comp = a[i].localeCompare(b[i])) !== 0) return comp;
}
return (a.length > b.length) - (a.length < b.length);
});
.localeCompare
还有一些选项可用于区分大小写、忽略标点符号、如何处理重音字符,以及其他一些。
根据您的评论和 per MDN ,与 Collator 对象(仅在某些浏览器中可用)相比,您可以获得更好的性能。根据文档(我自己只尝试过一次这段代码),它是这样工作的:
var collater = new Intl.Collator();
data.sort(function(a, b) {
var comp, i;
for (i = 0; i < Math.min(a.length, b.length); i++) {
if ((comp = collater.compare(a[i], b[i])) !== 0) return comp;
}
return (a.length > b.length) - (a.length < b.length);
});
大概必须有一些初始化或开销可以通过这种方式只完成一次。也许他们构建了直接查找排序表。
但是浏览器对 Collator 对象的支持很少(IE 11、Chrome、没有 Firefox、没有 Safari)所以除非你在浏览器插件中使用它,所以代码只特定于一个浏览器,你会有分支是否支持它并有两个实现。
附言如果你有相当数量的外部数组元素,因此多次调用排序回调,它的性能会非常糟糕。您至少可以让它每次只执行两次 JSON.stringify()
调用,而不是四次。
关于javascript - 这两种数组排序算法是否会对任何输入产生不同的输出?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19992253/