Eri*_*Yin 11 c# linq weighted-average weighted
让我们假设:
List<element> 哪个元素是:
public class Element(){
int Weight {get;set;}
}
Run Code Online (Sandbox Code Playgroud)
我想要实现的是,按重量随机选择一个元素.例如:
Element_1.Weight = 100;
Element_2.Weight = 50;
Element_3.Weight = 200;
Run Code Online (Sandbox Code Playgroud)
所以
Element_1选择的机会是100 /(100 + 50 + 200)= 28.57%Element_2选择的机会是50 /(100 + 50 + 200)= 14.29%Element_3选择的机会是200 /(100 + 50 + 200)= 57.14%我知道我可以创建一个循环,计算总数等...
我想要了解的是,Linq在一行(或尽可能短)中做到这一点的最佳方法,谢谢.
UPDATE
我在下面找到了答案.我学到的第一件事是:Linq不是魔术,它比设计良好的循环慢.
所以我的问题就是按重量找到一个随机元素,(尽可能短的东西:)
如果您想要通用版本(对于与(单例)随机化助手一起使用很有用,请考虑是否需要恒定种子)
用法:
randomizer.GetRandomItem(items, x => x.Weight)
Run Code Online (Sandbox Code Playgroud)
代码:
public T GetRandomItem<T>(IEnumerable<T> itemsEnumerable, Func<T, int> weightKey)
{
var items = itemsEnumerable.ToList();
var totalWeight = items.Sum(x => weightKey(x));
var randomWeightedIndex = _random.Next(totalWeight);
var itemWeightedIndex = 0;
foreach(var item in items)
{
itemWeightedIndex += weightKey(item);
if(randomWeightedIndex < itemWeightedIndex)
return item;
}
throw new ArgumentException("Collection count and weights must be greater than 0");
}
Run Code Online (Sandbox Code Playgroud)
// assuming rnd is an already instantiated instance of the Random class
var max = list.Sum(y => y.Weight);
var rand = rnd.Next(max);
var res = list
.FirstOrDefault(x => rand >= (max -= x.Weight));
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1762 次 |
| 最近记录: |