鈴木うどんの横須賀おもしろ生活

撮った写真や思ったことや技術ネタなど。出来るだけ大きなディスプレイで見ると良いと思う。ここでの発言は個人の見解であり、所属する組織の公式見解ではありません。

Javascript で Ruby の Array.sample

ruby だと

array = ['a', 'b', 'c', 'd', 'e', 'f']
array.sample 4
#=> ["f", "c", "a", "b"] 

みたいに書けるけれど Javascript のArray にそんな関数は無いので書いた。

Array.prototype.sample = function(num){
    num = num === undefined ? 1 : num;
    var self = this;
    var random_iter = (function(){
        // self の長さ分の 0 からの連番の配列をつくる
        var i = 0;
        var ary = Array.apply(null, Array(self.length)).map(function(){return i++});
        return {
            has_next: function(){
                return ary.length > 0;
            },
            next: function(){
                if(!this.has_next()) {
                    return null;
                }
                // 配列からランダムにインデックスを取得する
                return self[ary.splice(Math.floor(Math.random() * ary.length),1)];
            }
        }
    })();
    return Array.apply(null, Array(num)).map(function(){
        return random_iter.next();
    });
};

ランダムな値を返すイテレータを作る方針で書いた。num の長さの空の配列作るだけでArray.apply(null, Array(num)みたいに書かなくてはいけなくてとても悲しい思いをした。 常識的に考えて new Array(num) でどうにかなってほしいと思う。言語仕様的に説明つかなくなるのはわかるけれど、気持ちの問題だと思う。 あと、世の中的に builtin の prototype を勝手に拡張するとモヒカンがやってきて殴られるみたいなのあるけれど、習作だから問題無いということにしていただきたい。