如何在JavaScript中对字符串排序

2020/09/30 06:41 · javascript ·  · 0评论

我有一个希望基于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;

更新的答案(2014年10月)

我真的很讨厌这种字符串自然排序顺序,所以我花了很多时间来研究这个问题。我希望这有帮助。

长话短说

localeCompare()角色支持很糟糕,只需使用它即可。如所指出Shog9,您的问题的答案是:

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

在所有自定义javascript“自然字符串排序顺序”实现中发现的错误

有很多自定义实现,试图更精确地进行字符串比较,称为“自然字符串排序顺序”

在“玩弄”这些实现时,我总是注意到一些奇怪的“自然排序顺序”选择,或者是错误(或者在最佳情况下是遗漏)。

通常,特殊字符(空格,破折号,“&”号,方括号等)未正确处理。

然后,您会发现它们在不同的位置混合出现,通常可能是:

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

当一个人希望所有特殊字符都被“分组”在一个地方时,除了空格特殊字符(总是第一个字符)。也就是说,要么全部在数字之前,要么全部在数字和字母之间(小写字母和大写字母彼此“在一起”),或者全部在字母之后。

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

有关自定义实现的研究:

浏览器的本地“自然字符串排序顺序”实现通过 localeCompare()

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/上找到您可以在我发布的这个问题上找到有关此问题的更多信息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的好答,我相信我朝着“正确”的方向前进

答案(现代ECMAScript中)

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;
});

嵌套三元箭头功能

(a,b) => (a < b ? -1 : a > b ? 1 : 0)

由于可以在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成分,因为它们是例如内部程序常量,那么它===也可以使用。

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

item1.attr - item2.attr

因此,假设这些是数字(即item1.attr =“ 1”,item2.attr =“ 2”),只要确保输入类型,您仍然可以使用“ ===”运算符(或其他严格的求值器)。以下应该工作:

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

如果它们是alphaNumeric,则请使用localCompare()。

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>
var str = ['v','a','da','c','k','l']
var b = str.join('').split('').sort().reverse().join('')
console.log(b)
本文地址:http://javascript.askforanswer.com/ruhezaijavascriptzhongduizifuchuanpaixu.html
文章标签: ,  
版权声明:本文为原创文章,版权归 javascript 所有,欢迎分享本文,转载请保留出处!

文件下载

老薛主机终身7折优惠码boke112

上一篇:
下一篇:

评论已关闭!