如何在JavaScript中对string进行sorting

我有一个对象列表,我希望根据stringtypes的stringsorting。 我试过使用-

 list.sort(function (a, b) { return a.attr - b.attr }) 

但发现-似乎不适用于JavaScript中的string。 我怎样才能基于typesstring的属性sorting对象的列表?

这应该工作:

 if (item1.attr < item2.attr) return -1 if ( item1.attr > item2.attr) return 1 return 0 

更好的是,你可以使用String.prototype.localeCompare

 return item1.attr.localeCompare(item2.attr); 

更新的答案(2014年10月)

我真的很烦恼这个string自然sorting顺序,所以我花了相当一段时间来调查这个问题。 我希望这有帮助。

长话短说

localeCompare()字符的支持是坏蛋,只是使用它。 正如Shog9所指出的Shog9 ,你的问题的答案是:

 return item1.attr.localeCompare(item2.attr); 

在所有自定义javascript“自然stringsorting顺序”实现中发现的错误

在那里有相当多的自定义实现,试图做更精确的string比较称为“自然stringsorting顺序”

当“玩”这些实现时,我总是会注意到一些奇怪的“自然sorting”select,或者说是错误(或者在最好的情况下是遗漏的)。

通常,特殊字符(空格,短划线,&符,括号等)不能正确处理。

然后你会发现他们出现混合在不同的地方,通常可能是:

  • 一些将在大写字母“Z”和小写字母“a”之间
  • 有些会介于'9'和大写'A'之间
  • 有些会在小写字母“z”后面

当人们希望特殊字符在一个地方被“组合”在一起时,除了空格特殊字符(可能总是第一个字符)。 也就是说,无论是在数字之前,还是在数字和字母之间(小写字母和大写字母之间“连在一起”),或者全部在字母之后。

我的结论是,当我开始添加几乎不寻常的字符(即带有变音符号或字符(如短划线,感叹号等)的字符)时,它们都不能提供一致的顺序。

自定义实现的研究:

浏览器的本地“自然stringsorting”实现通过localeCompare()

localeCompare()最老的实现(没有语言环境和选项参数)支持IE6 +,请参阅http://msdn.microsoft.com/en-us/library/ie/s4esdbwz ( localeCompare() .aspx (向下滚动到localeCompare()方法)。 内置的localeCompare()方法在sorting上做得更好,甚至是国际化和特殊字符。 使用localeCompare()方法的唯一问题是“使用的语言环境和sorting顺序完全取决于实现”。 换句话说,当使用localeCompare比如stringOne.localeCompare(stringTwo)时:Firefox,Safari,Chrome和IE对Strings有不同的sorting顺序。

对浏览器本地实现的研究:

“string自然sorting”难度较大

实现一个可靠的algorithm(意味着:一致,但也涵盖了广泛的人物)是一项非常艰巨的任务。 UTF8包含超过2000个字符 , 涵盖超过120个脚本(语言) 。 最后,这个任务有一些规范,它被称为“Unicodesortingalgorithm”,可以在http://www.unicode.org/reports/tr10/find。; 你可以在这个问题上find更多关于这个问题的信息https://softwareengineering.stackexchange.com/questions/257286/is-there-any-language-agnostic-specification-for-string-natural-sorting-order

定论

所以考虑到我遇到的javascript自定义实现提供的当前支持水平,我们可能永远不会看到任何接近支持所有这些字符和脚本(语言)的东西。 因此,我宁愿使用浏览器的本地localeCompare()方法。 是的,它在浏览器中存在不一致的缺点,但基本的testing显示,它涵盖了更广泛的字符范围,允许有效的sorting。

正如Shog9所指出的Shog9 ,你的问题的答案是:

 return item1.attr.localeCompare(item2.attr); 

进一步阅读:

感谢Shog9的好回答,我相信这使得我处于“正确”的方向

你应该在这里使用>或<和==。 所以解决办法是:

 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. 

而已。 如果参数是完全相同的string(在相应的位置上具有相同的长度和相同的字符),则应用于string的三等于运算符将返回true。

所以===将在我们试图比较可能来自不同来源的string的情况下工作,但是我们知道它们最终会有相同的值 – 这是我们的代码中内联string的常见情况。 例如,如果我们有一个名为connection_state的variables,并且我们希望知道下面哪个状态['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. 

嗯。 现在怎么办? 外部获得的string可能,很可能会是奇怪的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中的string,请使用localeCompare ; 如果你知道string没有非ASCII组件,例如它们是内部程序常量,那么===也可以。

最简单的答案与ECMAScript 2016

 list.sort((a, b) => (a.attr > b.attr) - (a.attr < b.attr)) 

要么

 list.sort((a, b) => +(a.attr > b.attr) || -(a.attr < b.attr)) 
 list.sort(function(item1, item2){ return +(item1.attr > item2.attr) || +(item1.attr === item2.attr) - 1; }) 

https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/sort

在您最初的问题的操作中,您正在执行以下操作:

 item1.attr - item2.attr 

所以,假设这些是数字(即item1.attr =“1”,item2.attr =“2”),您仍然可以使用“===”运算符(或其他严格的评估者),只要您确保types。 以下应该工作:

 return parseInt(item1.attr) - parseInt(item2.attr); 

如果他们是alphaNumeric,那么请使用localCompare()。

我的最终实现

 var dataArr = { "hello": [{ "id": 114, "keyword": "zzzzzz", "region": "Korea", "supportGroup": "administrators", "category": "Category2" }, { "id": 115, "keyword": "aaaaa", "region": "Japan", "supportGroup": "developers", "category": "Category2" }] }; var sortArray = dataArr['hello']; sortArray.sort(function(a,b) { if ( a.region < b.region ) return -1; if ( a.region > b.region ) return 1; return 0; } );