概要
業務で数百件のデータをソートした時、IEとChromeによって結果が異なっていたので原因をメモ。
現象
ChromeでArray.prototype.sort()
を実施したとき、同じ値の順番が変更されていた。
原因
・v8エンジン詰んでるChrome
は、要素数によってソートロジックが変わる。
具体的には要素数が10より大きい値をソートする場合は、クイックソートを実行している。jsfiddle
let array = [
{'number': 1, 'value': 1},
{'number': 2, 'value': 1},
{'number': 3, 'value': 1},
{'number': 4, 'value': 1},
{'number': 5, 'value': 1},
{'number': 6, 'value': 1},
{'number': 7, 'value': 1},
{'number': 8, 'value': 1},
{'number': 9, 'value': 1},
{'number': 10, 'value': 1},
{'number': 11, 'value': 1}
];
// ソート対象の要素数が10より大きければ、v8エンジンはクイックソートを行う
array.sort((a,b) => {
return a.value > b.value ? 1 : -1;
});
console.log(array);
クイックソートは安定ソートではないので、順序が担保されないらしい・・・
今回はIE対応のみなので、無視でよかった・・・
Chromeで同値の順序を担保するなら、
別の配列に順序を別のプロパティとして保存 → 同値なら順序を考慮してソートを実施。jsfiddle
let array = [
{'number': 1, 'value': 1},
{'number': 2, 'value': 1},
{'number': 3, 'value': 1},
{'number': 4, 'value': 1},
{'number': 5, 'value': 1},
{'number': 6, 'value': 1},
{'number': 7, 'value': 1},
{'number': 8, 'value': 1},
{'number': 9, 'value': 1},
{'number': 10, 'value': 1},
{'number': 11, 'value': 1}
];
// ソート対象の要素数が10より大きければ、v8エンジンはクイックソートを行う
array.sort((a,b) => {
// 同値なら格納した順番を考慮
if (a.value === b.value) {
return a.number > b.number ? 1 : -1;
}
return a.value > b.value ? 1 : -1;
});
console.log(array);