jquery.vgrid.jsでランダムソートする時の注意

可変グリッドレイアウトのjQueryプラグインとして人気(だと思う)のjQueryプラグインにjquery.vgrid.jsというものがあります(可変グリッドレイアウトのjQueryプラグイン書いたよ | Xlune::Blog)
そのプラグインのサンプルとしてランダムソートを実装したページがあります。
demo007 – Dynamic Image Grid Example | jquery.vgrid.js
確かに、『Random Sort』ボタンを押すと、ランダムに並び替わっているように思えます。ソースコードを見てみると、下記のような実装方法になっていました。

$("#rsort").click(function(e){
	$("#grid-content").vgsort(function(a, b){
		return Math.random() > 0.5 ? 1 : -1 ;
	}, "easeInOutExpo", 300, 20);
	hsort_flg = true;
	return false;
});

2~4行目がソート用の記述になるようです。Math.random()関数で乱数を取得し、0.5より大きければ1を、小さければ-1を返すことでランダムな並び替えの実装をしているようです。
なお、上記のランダムソートの返り値部分は下記のようにすることもできます(参考:Javascript:javascriptで配列の中身をランダムに並び替える | raining)。

return Math.random() - 0.5;

ところでjquery.vgrid.jsに限った話ではないのですが、この方法には偏りがでてきます。並び替えの対象データが多ければ分かりにくいのですが、少ないと分かりやすいです。試しに先ほどのデモページから要素をDELETEという文字をクリックして消していき、10個ぐらいまでにしてみてからランダムボタンをクリックしてみてください。端の要素はほとんど動かないようになったと思います。

この偏りの解決策としては、Fisher-Yatesというアルゴリズムがあります。
参考:最速インターフェース研究会 :: 実践JavaScriptで配列をシャッフルする方法リファクタリング
ようは、while文で配列の最後の要素から順番に見ていき、それとランダムで選んだ要素のどれかと交換していくという方法です。単純だしこちらのほうが早いような気もします。

ただし、残念ながらjquery.vgrid.jsでは並び替え用の関数を渡す必要があるのでこの方法はつかえなさそうです。
ということで自分は、要素要素にランダム値を関連付けし、そのランダム値を見て昇順で並び替えるようにしました。
例えば、以下の様な感じです。

$('#grid-content div').each(function(){
    $(this).data("rand", Math.random());	
});

$("#grid-content").vgsort(function(a, b){
    return $(a).data("rand") - $(b).data("rand");
}, "easeInOutExpo", 300, 60);

2行目でjQueryのdata関数を使い、それぞれの要素にランダムな値を関連付けし、6行目でそのランダム値を見て昇順に並び替わるようにしています。全然凝ったことしてるわけではないのですが、sort用の関数を渡さなきゃいけない場合はこういう方法が使えるという参考までに。もっといい方法があれば教えてください。

以下、サンプルページ。
query.vgrid.jsを使ったランダムソートのサンプル

コメント

タイトルとURLをコピーしました