JavaScriptでシャッフルしようとしてハマったおはなし
忙しい人のための結論
collection = []; //中身を適当に埋める作業がここに入る sortedCollection = collection.sort(function(){ return Math.random() - 0.5; });
最初はこう書いていた
collection = []; //中身を適当に埋める作業がここに入る sortedCollection = collection.sort(function(){ return Math.random();}); /* *_人人人人人人人人人人人人人人_ *> なぜかシャッフルされない < * ̄Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y ̄ */
すべて正の数でも問題なくソートされるだろうと思っていたら間違いでした。
MDNにはこうあった
compareFunction が与えられた場合、配列の要素は比較関数の返り値に基づきソートされます。もし a と b が比較されようとしている要素の場合、
- compareFunction(a, b) が 0 未満の場合、a を b より小さい添字にソートします。
- compareFunction(a, b) が 0 を返す場合、a と b は互いに関して変えることなく、他のすべての要素に関してソートします。注意: ECMAScript 標準はこの振る舞いを保証しておらず、そのため一部のブラウザ (例えば、遅くとも 2003 年以前のバージョンの Mozilla) はこれを尊重していません。
- compareFunction(a, b) が 0 より大きい場合、b を a より小さい添字にソートします。
よって、比較関数は以下のような形式をもちます。
function compare(a, b) { if (ある順序の基準において a が b より小) return -1; if (その順序の基準において a が b より大) return 1; // a は b と等しいはず return 0; }
そりゃシャッフルされませんわ…
次にこう書いた
collection = []; //中身を適当に埋める作業がここに入る。 //ここらへんに collection[i]['compare'] = Math.random() 的なものが含まれる sortedCollection = collection.sort(function(a, b){ return a['compare'] - b['compare']; });
だがここで思ったのです。
(適当にシャッフルするんならわざわざ変数に持たせる必要ないのでは?)
そして書き換えた結果冒頭のコードになりました。