我有一个我希望根据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 1 以来localeCompare
一直受支持.您还可能会看到以下使用的代码不符合区域设置:
if (item1.attr < item2.attr) return -1; if ( item1.attr > item2.attr) return 1; return 0;
我真的很烦恼这个字符串自然排序顺序,所以我花了很长时间来研究这个问题.我希望这有帮助.
localeCompare()
角色支持是坏蛋,只需使用它.正如所指出的Shog9
,你的问题的答案是:
return item1.attr.localeCompare(item2.attr);
有很多自定义实现,尝试进行字符串比较更准确地称为"自然字符串排序顺序"
当"玩"这些实现时,我总是注意到一些奇怪的"自然排序顺序"选择,或者说错误(或者在最好的情况下的遗漏).
通常,不能正确处理特殊字符(空格,短划线,和号,括号等).
然后你会发现它们出现在不同的地方,通常可能是:
一些将在大写的'Z'和小写的'a'之间
一些将介于'9'和大写'A'之间
一些将在小写'z'之后
当人们期望特殊字符在一个地方被"分组"在一起时,除了空格特殊字符(可能始终是第一个字符).也就是说,要么全部在数字之前,要么全部在数字和字母之间(小写和大写一个接一个地"在一起"),或者全部在字母之后.
我的结论是,它们都未能提供一致的订单时,我开始增加几乎没有不寻常的字符(即用变音符号或charcters如破折号,感叹号等字符).
研究自定义实现:
Natural Compare Lite
https://github.com/litejs/natural-compare-lite:在整理排序时失败https://github.com/litejs/natural-compare-lite/issues/1和http://jsbin.com/bevututodavi/ 1 /编辑?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 /编辑?JS,控制台
Javascript Natural Sort
https://github.com/overset/javascript-natural-sort:自2012年2月以来似乎相当被忽视,一直排序失败,请参阅问题https://github.com/overset/javascript-natural-sort/issues/16
Alphanum
http://www.davekoelle.com/files/alphanum.js,一致排序失败,请参阅http://jsbin.com/tuminoxifuyo/1/edit?js,console
localeCompare()
localeCompare()
IE6 +支持最老的实现(没有locales和options参数),请参阅http://msdn.microsoft.com/en-us/library/ie/s4esdbwz (v=vs.94) .aspx(向下滚动到localeCompare( ) 方法).内置localeCompare()
方法在排序方面做得更好,甚至包括国际和特殊字符.使用该localeCompare()
方法的唯一问题是"使用的语言环境和排序顺序完全依赖于实现".换句话说,当使用localeCompare如stringOne.localeCompare(stringTwo)时:Firefox,Safari,Chrome和IE对字符串有不同的排序顺序.
研究浏览器本机实现:
http://jsbin.com/beboroyifomu/1/edit?js,console-与localeCompare()的 基本拉丁字符比较http://jsbin.com/viyucavudela/2/ - 与localeCompare()进行基本拉丁字符比较以进行测试IE8
http://jsbin.com/beboroyifomu/2/edit?js,console-字符串比较中的基本拉丁字符:字符串中的一致性检查
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/localeCompare - IE11 +支持新的语言环境和选项参数
实现一个可靠的算法(意思是:一致但也涵盖广泛的字符)是一项非常艰巨的任务.UTF8包含超过2000个字符,涵盖120多种脚本(语言).最后,这个任务有一些规范,它被称为"Unicode校对算法",可以在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);
https://softwareengineering.stackexchange.com/questions/257286/is-there-any-language-agnostic-specification-for-string-natural-sorting-order
你如何在JavaScript中进行字符串比较?
Javascript:自然的字母数字字符串
排序数字和字母元素的数组(自然排序)
对混合的字母/数字数组排序
https://web.archive.org/web/20130929122019/http://my.opera.com/GreyWyvern/blog/show.dml/1671288
https://web.archive.org/web/20131005224909/http://www.davekoelle.com/alphanum.html
http://snipplr.com/view/36012/javascript-natural-sort/
http://blog.codinghorror.com/sorting-for-humans-natural-sort-order/
感谢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:(x > y) - (y < x)
- > 1 - 0
- >1
x等于y:(x > y) - (y < x)
- > 0 - 0
- >0
x小于y:(x > y) - (y < x)
- > 0 - 1
- >-1
(替代)
x大于y:+(x > y) || -(x < y)
- > 1 || 0
- >1
x等于y:+(x > y) || -(x < y)
- > 0 || 0
- >0
x小于y:+(x > y) || -(x < y)
- > 0 || -1
- >-1
因此,这些逻辑等同于典型的排序比较器功能.
if (x == y) { return 0; } return x > y ? 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; });
我长期以来一直对此感到烦恼,所以我终于研究了这个并给你这个长期的理由,为什么事情就像他们一样.
从规格:
Section 11.9.4 The Strict Equals Operator ( === ) The production EqualityExpression : EqualityExpression === RelationalExpression is evaluated as follows: - Let lref be the result of evaluating EqualityExpression. - Let lval be GetValue(lref). - Let rref be the result of evaluating RelationalExpression. - Let rval be GetValue(rref). - Return the result of performing the strict equality comparison rval === lval. (See 11.9.6)
现在我们转到11.9.6
11.9.6 The Strict Equality Comparison Algorithm The comparison x === y, where x and y are values, produces true or false. Such a comparison is performed as follows: - If Type(x) is different from Type(y), return false. - If Type(x) is Undefined, return true. - If Type(x) is Null, return true. - If Type(x) is Number, then ... - If Type(x) is String, then return true if x and y are exactly the same sequence of characters (same length and same characters in corresponding positions); otherwise, return false.
而已.如果参数完全相同的字符串(相应位置的相同长度和相同字符),则应用于字符串的三重等于运算符将返回true.
因此===
,当我们尝试比较可能来自不同来源的字符串,但我们知道它们最终将具有相同的值时,这种情况会起作用 - 这是我们代码中内联字符串的常见情况.例如,如果我们有一个名为的变量connection_state
,并且我们希望知道它['connecting', 'connected', 'disconnecting', 'disconnected']
现在是以下哪个状态,我们可以直接使用===
.
但还有更多.在11.9.4之上,有一个简短的说明:
NOTE 4 Comparison of Strings uses a simple equality test on sequences of code unit values. There is no attempt to use the more complex, semantically oriented definitions of character or string equality and collating order defined in the Unicode specification. Therefore Strings values that are canonically equal according to the Unicode standard could test as unequal. In effect this algorithm assumes that both Strings are already in normalized form.
嗯.现在怎么办?外部获得的字符串可能,而且很可能会是奇怪的unicodey,而我们的温柔===
将不会公正.在localeCompare
救援中:
15.5.4.9 String.prototype.localeCompare (that) ... The actual return values are implementation-defined to permit implementers to encode additional information in the value, but the function is required to define a total ordering on all Strings and to return 0 when comparing Strings that are considered canonically equivalent by the Unicode standard.
我们现在可以回家了.
TL;博士;
要比较javascript中的字符串,请使用localeCompare
; 如果你知道字符串没有非ASCII组件,因为它们是,例如,内部程序常量,那么===
也可以工作.
嵌套三元箭头功能
(a,b) => (a < b ? -1 : a > b ? 1 : 0)