使用 ES2017 功能(如箭头函数和解构)的相同事物的较短版本:
功能
var stableSort = (arr, compare) => arr
.map((item, index) => ({item, index}))
.sort((a, b) => compare(a.item, b.item) || a.index - b.index)
.map(({item}) => item)
它接受输入数组和比较函数:
stableSort([5,6,3,2,1], (a, b) => a - b)
它还返回新数组,而不是像内置的 Array.sort() 函数那样进行就地排序。
测试
如果我们取以下input数组,最初按weight排序:
// sorted by weight
var input = [
{ height: 100, weight: 80 },
{ height: 90, weight: 90 },
{ height: 70, weight: 95 },
{ height: 100, weight: 100 },
{ height: 80, weight: 110 },
{ height: 110, weight: 115 },
{ height: 100, weight: 120 },
{ height: 70, weight: 125 },
{ height: 70, weight: 130 },
{ height: 100, weight: 135 },
{ height: 75, weight: 140 },
{ height: 70, weight: 140 }
]
然后使用stableSort按height排序:
stableSort(input, (a, b) => a.height - b.height)
结果:
// Items with the same height are still sorted by weight
// which means they preserved their relative order.
var stable = [
{ height: 70, weight: 95 },
{ height: 70, weight: 125 },
{ height: 70, weight: 130 },
{ height: 70, weight: 140 },
{ height: 75, weight: 140 },
{ height: 80, weight: 110 },
{ height: 90, weight: 90 },
{ height: 100, weight: 80 },
{ height: 100, weight: 100 },
{ height: 100, weight: 120 },
{ height: 100, weight: 135 },
{ height: 110, weight: 115 }
]
但是,使用内置的 Array.sort()(在 Chrome/NodeJS 中)对相同的 input 数组进行排序:
input.sort((a, b) => a.height - b.height)
返回:
var unstable = [
{ height: 70, weight: 140 },
{ height: 70, weight: 95 },
{ height: 70, weight: 125 },
{ height: 70, weight: 130 },
{ height: 75, weight: 140 },
{ height: 80, weight: 110 },
{ height: 90, weight: 90 },
{ height: 100, weight: 100 },
{ height: 100, weight: 80 },
{ height: 100, weight: 135 },
{ height: 100, weight: 120 },
{ height: 110, weight: 115 }
]
资源
更新
Array.prototype.sort 现已稳定在 V8 v7.0 / Chrome 70 中!
以前,V8 对超过 10 个元素的数组使用不稳定的快速排序。现在,我们使用稳定的 TimSort 算法。
source