c4se記:さっちゃんですよ☆

.。oO(さっちゃんですよヾ(〃l _ l)ノ゙☆)

.。oO(此のblogは、主に音樂考察Programming に分類されますよ。ヾ(〃l _ l)ノ゙♬♪♡)

音樂は SoundCloud に公開中です。

考察は現在は主に Scrapbox で公表中です。

Programming は GitHub で開發中です。

ElixirにてListのランダムな要素を取得する

追記:20170702
Enum.random/1を使ふのが好い。
Enum – Elixir v1.4.5

Rubyだと

xs.sample

である。JavaScriptだと

xs[Math.floor(Math.random() * xs.length)];

となる。Elixirでもこれに近いことを行ふ。Erlangのrandomモジュールを使ってみると

Enum.at(xs, :random.uniform(Enum.count xs) - 1)

となる。これでよささうに見える。しかし何回か試してみるとわかるが、randomの乱数列はシードが一定なのだ。手動でシードしてやらなければやらない。

:random.seed :os.timestamp
IO.inspect Enum.at(xs, :random.uniform(Enum.count xs) - 1)
IO.inspect Enum.at(xs, :random.uniform(Enum.count xs) - 1)
IO.inspect Enum.at(xs, :random.uniform(Enum.count xs) - 1)

:random.seed :os.timestamp
IO.inspect Enum.at(xs, :random.uniform(Enum.count xs) - 1)
IO.inspect Enum.at(xs, :random.uniform(Enum.count xs) - 1)
IO.inspect Enum.at(xs, :random.uniform(Enum.count xs) - 1)

これでよささうに見える。だがこのシードはプロセスごとに独立してゐるのだ。つまりプロセスを作るたびにプロセスの中でシードしてやらねばならない。しかもこれだとミリ秒の精度だから、プロセスを高速に大量につくるErlang (Elixir) では、頻繁にシードがかぶってしまふ。困る。
そこでrandomの代はりにcryptoモジュールを使ってみる。

Enum.at xs, rem(:crypto.bytes_to_integer(:crypto.rand_bytes 1), Enum.count xs)

重さうだが以上の欠点はない。cryptoの値でrandomをシードしてやるのもよいとおもふ。