LoginSignup
7
7

More than 5 years have passed since last update.

n個の数を重複なしでランダムに並べる

Last updated at Posted at 2012-12-26

配列をシャッフルする「Fisher-Yates法」というのがあるみたいなんだけど、
欲しいのはindexを並べ替えたものだけで
いちいち配列に数字を入れてからシャッフルするのも面倒なので
配列のiとかjの場所に数値がなければ、iとjをそのまま使うようにした。

function randomIndex(n){
    var i, j, tmp, a = new Array(n);
    a[0] = 0;
    for(i = n - 1; i > 0; i--) {
        j = Math.floor(Math.random() * (i+1));
        tmp = a[i] || i;
        a[i] = a[j] || j;
        a[j] = tmp;
    };
    return a;
}

console.log(randomIndex(10));
console.log(randomIndex(10));
console.log(randomIndex(10));
console.log(randomIndex(10));
console.log(randomIndex(10));

全indexの配列を先に作るのは無駄な気がしてきたので、
クロージャにして呼び出すたびに計算させるようにしてみた。
指定した数未満の数字を重複なしに呼び出して、全部出し終わったらnullを返す。

function makeBingo(n){
    var i, j, tmp, a = new Array(n);
    return function (){
        if(n > 0){
            i = n - 1;
            j = Math.floor(Math.random() * (n));
            tmp = a[i] || i;
            a[i] = a[j] || j;
            a[j] = tmp;
            n = i;
            return a[i];
        }else{
            return null;
        }
    }
};

var bingo = makeBingo(10);
for(var i=bingo();i!=null;i=bingo()){
    console.log(i);
};

2018/07/27 追記

こういうのを書きたかったということ。

var hukubiki = [
    "5等 ティッシュ1箱",
    "5等 ティッシュ1箱",
    "5等 ティッシュ1箱",
    "5等 ティッシュ1箱",
    "5等 ティッシュ1箱",
    "5等 ティッシュ1箱",
    "4等 クッキー詰め合わせ",
    "4等 クッキー詰め合わせ",
    "4等 クッキー詰め合わせ",
    "4等 クッキー詰め合わせ",
    "3等 炊飯器",
    "3等 炊飯器",
    "3等 炊飯器",
    "2等 大型テレビ",
    "2等 大型テレビ",
    "1等 ペアでハワイ旅行"
];

var bingo = makeBingo(hukubiki.length);
for(var i=bingo();i!=null;i=bingo()){
    console.log(hukubiki[i]);
};
7
7
0

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
7
7