我有一个希望基于attr
字符串类型的字段进行排序的对象列表。我尝试使用-
list.sort(function (a, b) {
return a.attr - b.attr
})
但发现-
在JavaScript 中似乎不适用于字符串。如何基于带有字符串类型的属性对对象列表进行排序?
Javascript : remove accents/diacritics in strings
在stackoverflow.com/questions/990904/...
我有一个希望基于attr
字符串类型的字段进行排序的对象列表。我尝试使用-
list.sort(function (a, b) {
return a.attr - b.attr
})
但发现-
在JavaScript 中似乎不适用于字符串。如何基于带有字符串类型的属性对对象列表进行排序?
Javascript : remove accents/diacritics in strings
在stackoverflow.com/questions/990904/...
Answers:
使用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()
不会遇到此问题,但不会理解数字,因此您可以像大多数语言中的排序比较一样获得[“ 1”,“ 10”,“ 2”]。如果您想对UI前端进行排序,请查看alphanum /自然排序算法stackoverflow.com/questions/4340227/…或stackoverflow.com/questions/4321829/…–
localeCompare()
只支持现代浏览器:在写作的时候IE11 +,看到developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/...
localeCompare()
回溯许多版本,但不支持指定 11版之前的语言环境。还要注意Dead.Rabit链接到的问题。
我真的很讨厌这种字符串自然排序顺序,所以我花了很多时间来研究这个问题。我希望这有帮助。
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/zh-cn/library/ie/s4esdbwz(v = vs.94).aspx(向下滚动到localeCompare( ) 方法)。内置localeCompare()
方法在排序(甚至国际字符和特殊字符)方面做得更好。使用该localeCompare()
方法的唯一问题是“使用的语言环境和排序顺序完全取决于实现”。换句话说,当使用诸如stringOne.localeCompare(stringTwo)之类的localeCompare时:Firefox,Safari,Chrome和IE对字符串的排序顺序不同。
对浏览器本地实现的研究:
实施可靠的算法(意味着:一致但又涵盖了广泛的字符)是一项艰巨的任务。UTF8包含2000多个字符,涵盖120多个脚本(语言)。最后,有一些针对此任务的规范,称为“ Unicode排序算法”,可以在http://www.unicode.org/reports/tr10/上找到。您可以在我发布的这个问题上找到有关此问题的更多信息/software/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;
localeCompare
和标准比较得出不同的结果。您期望哪个? ["A", "b", "C", "d"].sort((a, b) => a.localeCompare(b))
以不区分大小写的字母顺序排序,而["A", "b", "C", "d"].sort((a, b) => (a > b) - (a < b))
以代码点顺序排序
由于可以在javascript中直接比较字符串,因此可以完成工作
list.sort(function (a, b) {
return a.attr > b.attr ? 1: -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.
嗯 现在怎么办?外部获得的字符串可能而且很可能是奇怪的单一代码,而我们的绅士===
不会公平对待它们。在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; dr;
要比较javascript中的字符串,请使用localeCompare
; 如果您知道字符串没有非ASCII成分,因为它们是例如内部程序常量,那么它===
也可以使用。
list.sort(function(item1, item2){
return +(item1.attr > item2.attr) || +(item1.attr === item2.attr) - 1;
})
它们是如何工作的:
+('aaa'>'bbb')||+('aaa'==='bbb')-1
+(false)||+(false)-1
0||0-1
-1
+('bbb'>'aaa')||+('bbb'==='aaa')-1
+(true)||+(false)-1
1||0-1
1
+('aaa'>'aaa')||+('aaa'==='aaa')-1
+(false)||+(true)-1
0||1-1
0
<!doctype html>
<html>
<body>
<p id = "myString">zyxtspqnmdba</p>
<p id = "orderedString"></p>
<script>
var myString = document.getElementById("myString").innerHTML;
orderString(myString);
function orderString(str) {
var i = 0;
var myArray = str.split("");
while (i < str.length){
var j = i + 1;
while (j < str.length) {
if (myArray[j] < myArray[i]){
var temp = myArray[i];
myArray[i] = myArray[j];
myArray[j] = temp;
}
j++;
}
i++;
}
var newString = myArray.join("");
document.getElementById("orderedString").innerHTML = newString;
}
</script>
</body>
</html>
JavaScript case insensitive string comparison
上stackoverflow.com/questions/2140627/...