基于机会/怀特返回随机值的容器

时间:2013-02-14 12:46:40

标签: c# algorithm random containers

我如何才能最好地制作一个基于添加元素时输入的重量返回随机值的Container类?

理想情况下它应该像这样使用:

var randomContainer = new RandomContainer<IThing>();
randomContainer.Add(new CoolThing(), 80);
randomContainer.Add(new AwesomeThing(), 20);
IThing thing = randomContainer.Get();

因此,有80%的机会成为CoolThing,有20%的机会成为AwesomeThing。

但算法不应要求权重加起来为100,所以这也应该是可能的:

var randomContainer = new RandomContainer<IThing>();
randomContainer.Add(new CoolThing(), 398);
randomContainer.Add(new AwesomeThing(), 485);
randomContainer.Add(new SpecialThing(), 1);
IThing thing = randomContainer.Get();

任何想法如何实现这样的算法?班上应该有哪些会员/财产?实现ICollection是否有意义?

2 个答案:

答案 0 :(得分:1)

该算法应该非常简单:

选择1和所有权重之和的随机值。该值将指示要返回的对象。

第二个样本的示例:

  • 值1到398将返回CoolThing
  • 值399至883(= 398 + 485)将返回AwesomeThing
  • 值884将返回SpecialThing

答案 1 :(得分:1)

我将Daniel Hilgarth的答案标记为正确,因为他让我走上正轨。

对于任何想要实例的人:

public class RandomContainer<T> 
{
    private Random _random = new Random();

    private Dictionary<T, int> _objects = new Dictionary<T, int>();
    private int _weightSum;

    public RandomContainer()
    {           
    }

    public void Add(T obj, int weight)
    {          
        _objects.Add(obj, weight);
        _weightSum += weight;
    }

    public T Get()
    {
        int sumExtra = 0;
        int rand = _random.Next(0, _weightSum);
        foreach(var kvp in _objects)
        {
            if(rand < kvp.Value + sumExtra)
                return kvp.Key;
            sumExtra += kvp.Value;
        }
        return default(T); // This shouldn't be reached
    }
}

它不包含许多标准方法,但无论如何都是在Get()函数中,其余的应该很容易实现。