如何在JavaScript中对字符串进行排序

时间:2008-09-09 03:25:15

标签: javascript string

我有一个对象列表,我希望根据字符串类型的字段attr进行排序。我尝试使用-

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

但发现-似乎不适用于JavaScript中的字符串。如何根据类型为字符串的属性对对象列表进行排序?

14 个答案:

答案 0 :(得分:482)

根据您的示例使用String.prototype.localeCompare

list.sort(function (a, b) {
    return ('' + a.attr).localeCompare(b.attr);
})

我们强制a.attr为字符串以避免异常。已localeCompare支持if (item1.attr < item2.attr) return -1; if ( item1.attr > item2.attr) return 1; return 0; 和Firefox 1.您还可能会看到以下使用的代码不符合区域设置:

{{1}}

答案 1 :(得分:137)

更新的答案(2014年10月)

我对这个字符串自然排序顺序感到非常生气,所以我花了很长时间来研究这个问题。我希望这会有所帮助。

长话短说

localeCompare()角色支持是坏蛋,只需使用它。 正如Shog9所指出的,您的问题的答案是:

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

在所有自定义javascript&#34;自然字符串排序顺序中找到错误&#34;实现

有很多自定义实现,尝试进行字符串比较,更准确地称为&#34;自然字符串排序顺序&#34;

当&#34;播放&#34;通过这些实现,我总是注意到一些奇怪的&#34;自然排序顺序&#34;选择,或者说错误(或在最好的情况下的遗漏)。

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

然后,您会发现它们出现在不同的地方,通常可能是:

  • 有些将介于大写&#39; Z&#39;和小写的&#39; a&#39;
  • 有些人会介于&#39; 9&#39;和大写的&#39; <&#39;
  • 有些人会在小写&#39; z&#39;
  • 之后

当人们期望所有特殊字符都被&#34;分组&#34;在一个地方,除了空间特殊字符(可能永远是第一个字符)。也就是说,要么全部在数字之前,要么全部在数字和字母之间(小写和大写是&#34;在一起&#34;一个接一个),或者全部在数字和字母之后。

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

研究自定义实现:

浏览器&#39;本地&#34;自然字符串排序顺序&#34;通过localeCompare()

实现 IE6 +支持

localeCompare()最早的实现(没有locales和options参数),请参阅http://msdn.microsoft.com/en-us/library/ie/s4esdbwz(v=vs.94).aspx(向下滚动到localeCompare()方法)。 内置的localeCompare()方法在排序方面做得更好,甚至国际和特殊字符。 使用localeCompare()方法的唯一问题是"the locale and sort order used are entirely implementation dependent". In other words, when using localeCompare such as stringOne.localeCompare(stringTwo): Firefox, Safari, Chrome & IE have a different sort order for Strings.

研究浏览器原生实现:

&#34;字符串自然排序顺序&#34;

的难度

实现一个可靠的算法(意思是:一致但也涵盖广泛的字符)是一项非常艰巨的任务。 UTF8包含more than 2000 characters&amp; covers more than 120 scripts (languages)。 最后,这个任务有一些规范,它被称为&#34; Unicode校对算法&#34;,可以在http://www.unicode.org/reports/tr10/找到。您可以在我发布的https://softwareengineering.stackexchange.com/questions/257286/is-there-any-language-agnostic-specification-for-string-natural-sorting-order

这个问题上找到有关此问题的更多信息

最终结论

因此,考虑到我遇到的javascript自定义实现提供的当前支持级别,我们可能永远不会看到任何接近支持所有这些角色的内容。脚本(语言)。因此,我宁愿使用浏览器&#39; native localeCompare()方法。是的,它确实有不利于浏览器不一致的缺点,但基本的测试表明它涵盖了更广泛的字符,允许固体和有意义的排序顺序。

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

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

进一步阅读:

感谢Shog9给出了一个很好的答案,让我进入了#34;右边&#34;方向我相信

答案 2 :(得分:22)

答案(在现代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 - &gt; 1
  • false - &gt; 0

考虑三种可能的模式:

  • x大于y:(x > y) - (y < x) - &gt; 1 - 0 - &gt; 1
  • x等于y:(x > y) - (y < x) - &gt; 0 - 0 - &gt; 0
  • x小于y:(x > y) - (y < x) - &gt; 0 - 1 - &gt; -1

(替代)

  • x大于y:+(x > y) || -(x < y) - &gt; 1 || 0 - &gt; 1
  • x等于y:+(x > y) || -(x < y) - &gt; 0 || 0 - &gt; 0
  • x小于y:+(x > y) || -(x < y) - &gt; 0 || -1 - &gt; -1

因此,这些逻辑等同于典型的排序比较器功能。

if (x == y) {
    return 0;
}
return x > y ? 1 : -1;

答案 3 :(得分:9)

你应该使用&gt;或者&lt;和==这里。所以解决方案是:

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

答案 4 :(得分:5)

我长期以来一直对此感到困扰,所以我终于研究了这个问题并给出了这个长期的理由,说明为什么事情就是这样。

来自spec

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组件,因为它们是,例如,内部程序常量,那么===也可以。

答案 5 :(得分:5)

因为可以在javascript中直接比较字符串,所以可以完成

for

仅当需要非字母(数字)排序,并且当然不适用于字符串时,才使用排序函数中的减法

答案 6 :(得分:1)

嵌套三元箭头功能

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

答案 7 :(得分:1)

为什么问题中的方法不起作用的解释:

let products = [
    { name: "laptop", price: 800 },
    { name: "phone", price:200},
    { name: "tv", price: 1200}
];
products.sort( (a, b) => {
    {let value= a.name - b.name; console.log(value); return value}
});

> 2 NaN

字符串之间的减法返回NaN。

呼应@Alejadro的答案,正确的方法是-

products.sort( (a,b) => a.name > b.name ? 1 : -1 )

答案 8 :(得分:0)

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

item1.attr - item2.attr

因此,假设这些是数字(即item1.attr =“1”,item2.attr =“2”)。如果确保类型,您仍然可以使用“===”运算符(或其他严格的赋值程序)。以下应该有效:

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

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

答案 9 :(得分:0)

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

答案 10 :(得分:0)

直接使用 sort(),不带任何 -<

const areas = ['hill', 'beach', 'desert', 'mountain']
console.log(areas.sort())

// To print in descending way
console.log(areas.sort().reverse())

答案 11 :(得分:0)

应该有升序和降序函数

            if (order === 'asc') {
                return a.localeCompare(b);
            }
            return b.localeCompare(a);

答案 12 :(得分:-1)

<!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>

答案 13 :(得分:-1)

var str = ['v','a','da','c','k','l']
var b = str.join('').split('').sort().reverse().join('')
console.log(b)