From: Yusuke ENDOH <mame@...> Date: 2010-12-21T01:32:20+09:00 Subject: [ruby-dev:42829] Re: [Ruby 1.9-Feature#4147] Array#sample で重みを指定したい 遠藤です。 2010年12月20日22:33 Yoji Ojima <redmine@ruby-lang.org>: >>「重みを変えずに繰り返し抽選したい」というユースケースで有利になる >>んですが、汎用性に欠けますかね。結構ありそうだと思うんですが。 > > ほとんどの場合は一回の呼び出しで大量の抽出を行うことで代替可能ではないでしょうか。 最初に大量抽出でプールしておいて、ちょっとずつ消費し、無くなったら また大量抽出してプールする、というデバッグが面倒なコードをユーザに 書かせることになるのはよくないと思います。 > 繰り返しになりますが、二分探索は最適なアルゴリズムではない(簡便性を犠牲にする割に半端にしか速くならない)というのも重要な点で、高速な細切れ抽出を本当に求めるのであれば、以下のサイトのコードのように専用のクラスを用意するのが適切だと思います。 > http://code.activestate.com/recipes/576564-walkers-alias-method-for-random-objects-with-diffe/ > しかしながら、これは組み込みライブラリでサポートすべき範疇ではないでしょう。 確かに組み込みにするには大掛かりすぎると思います。 しかしある程度ちゃんと対応しようとしたら大掛かりな API が必要である 以上、組み込みにするのが不適切なのではないかという気もします。 重み付き sample を本気で使おうとして困った人が「O(n) かかって遅いん だけどなんでこんな API にしたの」と言ってきたときに、「重み付き sample はおみくじ専用なので本気で使わないでください」とかアホなこと 言いたくないですし、本気で使うときは自力で書き直すのが定番になるのも 嬉しくないです。 ところで以前 naruse さんが (IRC で) 言ってたアイデアなのですが、 Enumerator で返すという API が考えられます。つまり、 e = %(大吉 中吉 小吉 凶).sample_each e.each {|x| p x } #=> 凶 中吉 大吉 小吉 e = %(大吉 中吉 小吉 凶).sample_each(unique: false, weight: [1000, 100, 10, 1]) e.each {|x| p x } #=> 大吉 大吉 中吉 大吉 ... これが実は相性いいかもしれない? -- Yusuke Endoh <mame@tsg.ne.jp>