在C#中按重量选择随机元素的最简洁方法是什么? [英] Whats the most concise way to pick a random element by weight in c#?
问题描述
让我们假设:
List<element>
哪个元素是:
public class Element(){
int Weight {get;set;}
}
我要实现的是,根据重量随机选择一个元素. 例如:
What I want to achieve is, select an element randomly by the weight. For example:
Element_1.Weight = 100;
Element_2.Weight = 50;
Element_3.Weight = 200;
所以
-
Element_1
被选中的机会是100/(100 + 50 + 200)= 28.57% - 选择
Element_2
的机会是50/(100 + 50 + 200)= 14.29% -
Element_3
被选中的机会是200/(100 + 50 + 200)= 57.14%
- the chance
Element_1
got selected is 100/(100+50+200)=28.57% - the chance
Element_2
got selected is 50/(100+50+200)=14.29% - the chance
Element_3
got selected is 200/(100+50+200)=57.14%
我知道我可以创建一个循环,计算总数,等等...
I know I can create a loop, calculate total, etc...
我想学习的是,Linq在1行(或尽可能短)中执行此操作的最佳方法是什么,谢谢.
更新
我在下面找到了答案.我学到的第一件事是: Linq不是魔术,它比设计周密的循环要慢.
I found my answer below. First thing I learn is: Linq is NOT magic, it's slower then well-designed loop.
所以我的问题变成了按重量查找随机元素((没有尽可能短的内容:)
So my question becomes find a random element by weight, (without as short as possible stuff :)
推荐答案
如果您想要一个通用版本(用于与(单个)随机化助手一起使用,请考虑是否需要恒定种子或不是)
If you want a generic version (useful for using with a (singleton) randomize helper, consider whether you need a constant seed or not)
用法:
randomizer.GetRandomItem(items, x => x.Weight)
代码:
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");
}
这篇关于在C#中按重量选择随机元素的最简洁方法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!