Search code examples
c#listrandomprobability

Pick random element from list with probability


I Have a list that contains four item (A, B, C, D). Every item has a probability to be chosen. Let's say for example A has 74% of chance to be picked, B 15%, C 7% ,and D 4%.

I want to create a function that choose randomly an item according to its probability.

Any help please?


Solution

  • Define a class for your items like this:

    class Items<T>
    {
        public double Probability { get; set; }
        public T Item { get; set; }
    }
    

    then initialize it

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

    then you need to convert it to aggregate a sum of probabilities from 0 to 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});
    

    now you can pick an item from converted collection with respect to probability:

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

    NOTE: my implementation have O(n) complexity. You can optimize it with binary search (because values in converted collection are sorted)