我有一个对象列表,我希望根据字符串类型的字段attr
进行排序。我尝试使用-
list.sort(function (a, b) {
return a.attr - b.attr
})
但发现-
似乎不适用于JavaScript中的字符串。如何根据类型为字符串的属性对对象列表进行排序?
答案 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)
我对这个字符串自然排序顺序感到非常生气,所以我花了很长时间来研究这个问题。我希望这会有所帮助。
localeCompare()
角色支持是坏蛋,只需使用它。
正如Shog9
所指出的,您的问题的答案是:
return item1.attr.localeCompare(item2.attr);
有很多自定义实现,尝试进行字符串比较,更准确地称为&#34;自然字符串排序顺序&#34;
当&#34;播放&#34;通过这些实现,我总是注意到一些奇怪的&#34;自然排序顺序&#34;选择,或者说错误(或在最好的情况下的遗漏)。
通常,特殊字符(空格,短划线,&符号,括号等)未正确处理。
然后,您会发现它们出现在不同的地方,通常可能是:
当人们期望所有特殊字符都被&#34;分组&#34;在一个地方,除了空间特殊字符(可能永远是第一个字符)。也就是说,要么全部在数字之前,要么全部在数字和字母之间(小写和大写是&#34;在一起&#34;一个接一个),或者全部在数字和字母之后。
我的结论是,当我开始添加几乎不常见的字符(即带有变音符号或字符,如短划线,感叹号等)时,它们都无法提供一致的顺序。
研究自定义实现:
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,console 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()
最早的实现(没有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.
研究浏览器原生实现:
实现一个可靠的算法(意思是:一致但也涵盖广泛的字符)是一项非常艰巨的任务。 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)
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) - (y < x)
- &gt; 1 - 0
- &gt; 1
(x > y) - (y < x)
- &gt; 0 - 0
- &gt; 0
(x > y) - (y < x)
- &gt; 0 - 1
- &gt; -1
(替代)
+(x > y) || -(x < y)
- &gt; 1 || 0
- &gt; 1
+(x > y) || -(x < y)
- &gt; 0 || 0
- &gt; 0
+(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)