aTreeMap
が本当にこれに最適なデータ構造であるかどうかはわかりませんが、. . .
このメソッドを使用して、Math.random()
0.0
(包括的) と1.0
(排他的)の間のランダムな値を取得できます。次に、その値を超えるまで、マップの要素を繰り返し、頻度を累積します。この値を最初に超えるサフィックスが結果です。マップ要素の頻度がすべて合計されると仮定すると1.0
、これにより、頻度に比例してすべての接尾辞が選択されます。
例えば:
public class Demo
{
private final Map<String, Double> suffixFrequencies =
new TreeMap<String, Double>();
private String getRandomSuffix()
{
final double value = Math.random();
double accum = 0.0;
for(final Map.Entry<String, Double> e : suffixFrequencies.entrySet())
{
accum += e.getValue();
if(accum > value)
return e.getKey();
}
throw new AssertionError(); // or something
}
public static void main(final String... args)
{
final Demo demo = new Demo();
demo.suffixFrequencies.put("abc", 0.3); // value in [0.0, 0.3)
demo.suffixFrequencies.put("def", 0.2); // value in [0.3, 0.5)
demo.suffixFrequencies.put("ghi", 0.5); // value in [0.5, 1.0)
// Print "abc" approximately three times, "def" approximately twice,
// and "ghi" approximately five times:
for(int i = 0; i < 10; ++i)
System.out.println(demo.getRandomSuffix());
}
}
ノート:
- 丸め誤差のため、非常にまれではありますが、
throw new AssertionError()
実際には頻繁に発生する可能性があります。そのため、その行を常に最初の要素または最後の要素などを選択するものに置き換えることをお勧めします。
- 周波数の合計がすべて 1.0 にならない場合は、最初にパスを追加して
getRandomSuffix()
、すべての周波数の合計を決定する必要があります。その後、それに応じてスケーリングできますvalue
。