Whats the most concise way to pick a random element by weight in c#?

后端 未结 4 2039
慢半拍i
慢半拍i 2021-01-02 03:57

Lets assume:

List which element is:

public class Element(){
   int Weight {get;set;}
}

What I want to a

4条回答
  •  萌比男神i
    2021-01-02 04:42

    This could work:

    int weightsSum = list.Sum(element => element.Weight);
    int start = 1;
    var partitions = list.Select(element => 
                     { 
                       var oldStart = start;
                       start += element.Weight;
                       return new { Element = element, End = oldStart + element.Weight - 1};
                     });
    
    var randomWeight = random.Next(weightsSum);
    var randomElement = partitions.First(partition => (partition.End > randomWeight)).
                                   Select(partition => partition.Element);
    

    Basically, for each element a partition is created with an end weight. In your example, Element1 would associated to (1-->100), Element2 associated to (101-->151) and so on...

    Then a random weight sum is calculated and we look for the range which is associated to it.

    You could also compute the sum in the method group but that would introduce another side effect...

    Note that I'm not saying this is elegant or fast. But it does use linq (not in one line...)

提交回复
热议问题