[7,-2,2,-7,-3].sort() = [-2,-3,-7,2,-7]
以下是前端FB社團看到的解釋 :
因為 JavaScript 預設的比較函式是
(a, b) => a.toString().localeCompare(b)
也就是先將輸入轉為字串 (所以上述就是 "-" 排在數字之前比較,第二個字元再來比順序),並依據區域化設定而會不同的排序結果 —— 舉例來說,如果你的語系設定為捷克語 (分類上算是西斯拉夫語支),以 "CH" 開頭的字串要排在 "H" 之後,但單看字母的話,"C" 要在 "B" 之後。
光是排序的規則就可以探討一陣子,我們該如何誠實面對自身對 JavaScript 的無力呢?
想請問大家怎麼解決JS的排序問題呢?
有推薦的第三方庫?
更新
嘗試第一種方式 : JavaScript中sort方法排序不正確解決辦法_weixin_36309908的博客-CSDN博客
var arr = [7,-2,2,-7,-3];
arr.sort(function (a,b) {
if (a < b ) return -1;
if (a > b ) return 1;
return 0;
});
結果 : 可以,但需要每一次排序自己實現方法
嘗試2 : 從 V8 源碼看 JS 數組排序的詭異問題 - 前端進階 - SegmentFault 思否
var arr = [7,-2,2,-7,-3];
arr.sort((x, y) => x - y);
結果 : OK,而且也簡短好多,但會有先map再sort
跟先sort再map
結果可能會不一樣問題,貞操蛋 = v =
文中補充 :
如果
comparefn(a, b)
等於0
,a
和b
的相對位置不變。備註:ECMAScript 標準並不保證這一行為,而且也不是所有瀏覽器都會遵守。
翻譯成編程術語就是:sort
排序算法是不穩定排序。
先map再sort
跟先sort再map
結果可能會不一樣問題
//異常排序
var data = [
{value: 4},
{value: 2},
{value: undefined},
{value: undefined},
{value: 1},
{value: undefined},
{value: undefined},
{value: 7},
{value: undefined},
{value: 4}
];
data
.sort((x, y) => x.value - y.value)
.map(x => x.value);
// result : (10) [2, 4, undefined, undefined, 1, undefined, undefined, 4, 7, undefined]
//能正常排序
var data = [
{value: 4},
{value: 2},
{value: undefined},
{value: undefined},
{value: 1},
{value: undefined},
{value: undefined},
{value: 7},
{value: undefined},
{value: 4}
];
data
.map(x => x.value)
.sort((x, y) => x.value - y.value);
// result : [4, 2, 1, 7, 4, undefined, undefined, undefined, undefined, undefined]
嘗試 3 :
listennn08 :
lodash
_.sortBy(data, (el) => el.value)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
<script>
//能正常排序
var data = [
{value: 4},
{value: 2},
{value: undefined},
{value: undefined},
{value: 1},
{value: undefined},
{value: undefined},
{value: 7},
{value: undefined},
{value: 4}
];
var sorted =
_.map(
_.sortBy(data, (el) => el.value)
,(el) => el.value
)
;
console.log(sorted);//[1, 2, 4, 4, 7, undefined, undefined, undefined, undefined, undefined]
</script>
結果 : 目前測試以來效果最好的
文件 : lodash.map | Lodash 中文网
Array.prototype.mysort = function() {
return this.sort(function(a, b) {
return a - b;
})
}
[7,-2,2,-7,-3, 27].mysort()
output -> [-7, -3, -2, 2, 7, 27]
感謝您
我目前找到最簡短的也是這樣,但看這篇文章 从 V8 源码看 JS 数组排序的诡异问题 - 前端进阶 - SegmentFault 思否 此方式會有以下問題先map再sort跟先sort再map結果可能會不一樣
但這應該算是另外新的問題了
//異常排序
var data = [
{value: 4},
{value: 2},
{value: undefined},
{value: undefined},
{value: 1},
{value: undefined},
{value: undefined},
{value: 7},
{value: undefined},
{value: 4}
];
data
.sort((x, y) => x.value - y.value)
.map(x => x.value);
// result : (10) [2, 4, undefined, undefined, 1, undefined, undefined, 4, 7, undefined]
//能正常排序
var data = [
{value: 4},
{value: 2},
{value: undefined},
{value: undefined},
{value: 1},
{value: undefined},
{value: undefined},
{value: 7},
{value: undefined},
{value: 4}
];
data
.map(x => x.value)
.sort((x, y) => x.value - y.value);
// result : [4, 2, 1, 7, 4, undefined, undefined, undefined, undefined, undefined]
但目前找到的原生sort解決方案,都多多少少會有兼容性問題
這不算是兼容性問題,是沒有定義好 undefined 在比較時要怎麼處理
定義好結果就會正確了
var data = [
{value: 4},
{value: 2},
{value: undefined},
{value: undefined},
{value: 1},
{value: undefined},
{value: undefined},
{value: 7},
{value: undefined},
{value: 4}
];
data.sort((a, b)=>{
var type_a = typeof a.value ==='number' ? 0 : 1;
var type_b = typeof b.value ==='number' ? 0 : 1;
if(type_a|type_b) {
return type_a-type_b;
}
return a.value-b.value;
});