0

我将如何最好地制作一个 Container 类,该类根据在添加元素期间输入的权重返回随机值?

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

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

所以 thing 有 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 有意义吗?

4

2 回答 2

1

该算法应该非常简单:

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

第二个示例的示例:

  • 值 1 到 398 将返回CoolThing
  • 值 399 到 883 (= 398 + 485) 将返回AwesomeThing
  • 值 884 将返回SpecialThing
于 2013-02-14T12:53:25.493 回答
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() 函数,其余的应该很容易实现。

于 2013-02-14T14:21:48.380 回答