以概率从列表中选择随机元素

问题描述 投票:0回答:3

我有一个包含四个项目(A、B、C、D)的列表。每个项目都有被选择的概率。举例来说,A 有 74% 的机会被选中,B 15%,C 7%,D 4%。

我想创建一个函数,根据其概率随机选择一个项目。

请问有什么帮助吗?

c# list random probability
3个回答
7
投票

为您的项目定义一个类,如下所示:

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)
集合中的值已排序)
    


2
投票

无论如何,这是我的尝试:

converted

用途:

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; } }



-1
投票
	
© www.soinside.com 2019 - 2024. All rights reserved.