我有一个对象列表,我希望根据attr
字符串类型的字段进行排序。我尝试使用-
list.sort(function (a, b) {
return a.attr - b.attr
})
但发现它-
似乎不适用于 JavaScript 中的字符串。如何根据类型为字符串的属性对对象列表进行排序?
我有一个对象列表,我希望根据attr
字符串类型的字段进行排序。我尝试使用-
list.sort(function (a, b) {
return a.attr - b.attr
})
但发现它-
似乎不适用于 JavaScript 中的字符串。如何根据类型为字符串的属性对对象列表进行排序?
String.prototype.localeCompare
根据您的示例使用一个:
list.sort(function (a, b) {
return ('' + a.attr).localeCompare(b.attr);
})
我们强制 a.attr 为字符串以避免异常。自 Internet Explorer 6和 Firefox 1localeCompare
起就已受支持。您可能还会看到使用了以下不考虑区域设置的代码:
if (item1.attr < item2.attr)
return -1;
if ( item1.attr > item2.attr)
return 1;
return 0;
我真的对这个字符串自然排序顺序很恼火,所以我花了很多时间来调查这个问题。我希望这有帮助。
localeCompare()
角色支持很糟糕,只需使用它。正如所指出的Shog9
,你的问题的答案是:
return item1.attr.localeCompare(item2.attr);
有很多自定义实现,试图更准确地进行字符串比较,称为“自然字符串排序顺序”
当“玩”这些实现时,我总是注意到一些奇怪的“自然排序顺序”选择,或者更确切地说是错误(或在最好的情况下遗漏)。
通常,特殊字符(空格、破折号、与号、方括号等)无法正确处理。
然后您会发现它们出现在不同的地方,通常可能是:
当人们期望特殊字符全部“组合”在一个地方时,除了空格特殊字符(可能总是第一个字符)。也就是说,要么全部在数字之前,要么全部在数字和字母之间(小写和大写字母一个接一个地“一起”),或者全部在字母之后。
我的结论是,当我开始添加几乎不常见的字符(即带有变音符号或字符,如破折号、感叹号等)时,它们都无法提供一致的顺序。
对自定义实现的研究:
Natural Compare Lite
https://github.com/litejs/natural-compare-lite:始终无法进行排序https://github.com/litejs/natural-compare-lite/issues/1和http://jsbin.com/bevututodavi/ 1/edit?js,console基本拉丁字符排序http://jsbin.com/bevututodavi/5/edit?js,console Natural Sort
https://github.com/javve/natural-sort:始终无法排序,请参阅问题https://github.com/javve/natural-sort/issues/7并查看基本的拉丁字符排序http://jsbin。 com/cipimosedoqe/3/edit?js,控制台 Javascript Natural Sort
https://github.com/overset/javascript-natural-sort:自 2012 年 2 月以来似乎相当被忽视,始终无法进行排序,请参阅问题https://github.com/overset/javascript-natural-sort/issues/16Alphanum
http://www.davekoelle.com/files/alphanum.js,排序失败,请参见http://jsbin.com/tuminoxifuyo/1/edit?js,consolelocaleCompare()
localeCompare()
IE6+ 支持最旧的实现(没有语言环境和选项参数),请参阅http://msdn.microsoft.com/en-us/library/ie/s4esdbwz (v=vs.94) .aspx(向下滚动到 localeCompare( ) 方法)。内置localeCompare()
方法在排序方面做得更好,甚至是国际和特殊字符。使用该localeCompare()
方法的唯一问题是“使用的语言环境和排序顺序完全取决于实现”。换句话说,当使用诸如 stringOne.localeCompare(stringTwo) 之类的 localeCompare 时:Firefox、Safari、Chrome 和 IE 对字符串有不同的排序顺序。
浏览器原生实现的研究:
实现一个可靠的算法(意思是:一致但也涵盖广泛的字符)是一项非常艰巨的任务。UTF8 包含2000 多个字符并涵盖 120 多种脚本(语言)。最后,这个任务有一些规范,它被称为“Unicode Collation Algorithm”,可以在http://www.unicode.org/reports/tr10/找到。您可以在我发布的这个问题上找到有关此问题的更多信息https://softwareengineering.stackexchange.com/questions/257286/is-there-any-language-agnostic-specification-for-string-natural-sorting-order
因此,考虑到我遇到的 javascript 自定义实现提供的当前支持水平,我们可能永远不会看到任何接近支持所有这些字符和脚本(语言)的东西。因此,我宁愿使用浏览器的本地 localeCompare() 方法。是的,它确实有跨浏览器不一致的缺点,但基本测试表明它涵盖了更广泛的字符,允许可靠且有意义的排序顺序。
因此,正如 所指出的Shog9
,您的问题的答案是:
return item1.attr.localeCompare(item2.attr);
感谢 Shog9 的好回答,这让我朝着“正确”的方向发展,我相信
list.sort((a, b) => (a.attr > b.attr) - (a.attr < b.attr))
或者
list.sort((a, b) => +(a.attr > b.attr) || -(a.attr < b.attr))
将布尔值转换为数字会产生以下结果:
true
-> 1
false
-> 0
考虑三种可能的模式:
(x > y) - (y < x)
-> 1 - 0
->1
(x > y) - (y < x)
-> 0 - 0
->0
(x > y) - (y < x)
-> 0 - 1
->-1
(选择)
+(x > y) || -(x < y)
-> 1 || 0
->1
+(x > y) || -(x < y)
-> 0 || 0
->0
+(x > y) || -(x < y)
-> 0 || -1
->-1
所以这些逻辑相当于典型的排序比较器功能。
if (x == y) {
return 0;
}
return x > y ? 1 : -1;
由于字符串可以直接在 javascript 中进行比较,这将完成这项工作
list.sort(function (a, b) {
return a.attr > b.attr ? 1: -1;
})
排序函数中的减法仅在需要非字母(数字)排序时使用,当然它不适用于字符串
您应该在这里使用 > 或 < 和 ==。所以解决方案是:
list.sort(function(item1, item2) {
var val1 = item1.attr,
val2 = item2.attr;
if (val1 == val2) return 0;
if (val1 > val2) return 1;
if (val1 < val2) return -1;
});