LoginSignup
3

More than 5 years have passed since last update.

【JavaScript】同じ値が正しくソートされない【Chrome】

Last updated at Posted at 2018-03-03

概要

業務で数百件のデータをソートした時、IEとChromeによって結果が異なっていたので原因をメモ。

現象

ChromeでArray.prototype.sort()を実施したとき、同じ値の順番が変更されていた。

原因

・v8エンジン詰んでるChromeは、要素数によってソートロジックが変わる。

参照:http://kakts-tec.hatenablog.com/entry/2016/12/18/153845

具体的には要素数が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);

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3