I 4つの項目(A、B、C、D)を含むリストがあります。すべてのアイテムが選択される可能性があります。たとえば、Aが選択される確率は74%、B 15%、C 7%、D 4%です。確率がリストからランダム要素を選択
その確率に従ってアイテムをランダムに選択する関数を作成したいと考えています。
お願いします。
I 4つの項目(A、B、C、D)を含むリストがあります。すべてのアイテムが選択される可能性があります。たとえば、Aが選択される確率は74%、B 15%、C 7%、D 4%です。確率がリストからランダム要素を選択
その確率に従ってアイテムをランダムに選択する関数を作成したいと考えています。
お願いします。
は、このようなあなたの項目のためのクラスを定義します。
class Items<T>
{
public double Probability { get; set; }
public T Item { get; set; }
}
は、それが
var initial = new List<Items<string>>
{
new Items<string> {Probability = 74/100.0, Item = "A"},
new Items<string> {Probability = 15/100.0, Item = "B"},
new Items<string> {Probability = 7/100.0, Item = "C"},
new Items<string> {Probability = 4/100.0, Item = "D"},
};
、あなたは合計を集計するためにそれを変換する必要が初期化0から1の可能性の数
var converted = new List<Items<string>>(initial.Count);
var sum = 0.0;
foreach (var item in initial.Take(initial.Count - 1))
{
sum += item.Probability;
converted.Add(new Items<string> {Probability = sum, Item = item.Item});
}
converted.Add(new Items<string> {Probability = 1.0, Item = initial.Last().Item});
今あなたが確率に関してconverted
コレクションから項目を選ぶことができます。
var rnd = new Random();
while (true)
{
var probability = rnd.NextDouble();
var selected = converted.SkipWhile(i => i.Probability < probability).First();
Console.WriteLine($"Selected item = {selected.Item}");
}
注:私の実装では、O(n)
複雑さを持っています。私はちょっと「Euler.Net」パズルの一種として、それを見てると、 - あなたは(converted
コレクション内の値がソートされているため)
Thnx bro ....... –
1〜100の数字を選んで、そのカテゴリに該当するかどうかを確認するのが最善です。
擬似コード -
x = randnum(1-100)
if 1 <= x < 50:
#50%, etc.
using System;
public class Test{
private static String[] values = {"A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","B","B","B","B","B","B","B","B","B","B","B","B","B","B","B","C","C","C","C","C","C","C","D","D","D","D",};
private static Random PRNG = new Random();
public static void Main(){
Console.WriteLine(values[PRNG.Next(values.Length)]);
}
}
バイナリ検索でそれを最適化することができますジェネリックスで遊ぶ方法。とにかく
、ここに私のGoはそれでだ:
public class WeightedItem<T>
{
private T value;
private int weight;
private int cumulativeSum;
private static Random rndInst = new Random();
public WeightedItem(T value, int weight)
{
this.value = value;
this.weight = weight;
}
public static T Choose(List<WeightedItem<T>> items)
{
int cumulSum = 0;
int cnt = items.Count();
for (int slot = 0; slot < cnt; slot++)
{
cumulSum += items[slot].weight;
items[slot].cumulativeSum = cumulSum;
}
double divSpot = rndInst.NextDouble() * cumulSum;
WeightedItem<T> chosen = items.FirstOrDefault(i => i.cumulativeSum >= divSpot);
if (chosen == null) throw new Exception("No item chosen - there seems to be a problem with the probability distribution.");
return chosen.value;
}
}
は使用方法:
WeightedItem<string> alice = new WeightedItem<string>("alice", 1);
WeightedItem<string> bob = new WeightedItem<string>("bob", 1);
WeightedItem<string> charlie = new WeightedItem<string>("charlie", 1);
WeightedItem<string> diana = new WeightedItem<string>("diana", 4);
WeightedItem<string> elaine = new WeightedItem<string>("elaine", 1);
List<WeightedItem<string>> myList = new List<WeightedItem<string>> { alice, bob, charlie, diana, elaine };
string chosen = WeightedItem<string>.Choose(myList);
あなたはまずそれを試してみる必要があり、私たちは、あなたが遭遇するあらゆる問題であなたをお手伝いします。 SOはあなたのために完全にコードを書いていません。 – Sach
[random.choiceの加重バージョン](https://stackoverflow.com/questions/3679694/a-weighted-version-of-random-choice)の重複の可能性あり –
可能な複製https://stackoverflow.com/質問/ 9330394 /どのようにしてアイテムを選択するか –