在C#中按重量选择随机元素的最简洁方法是什么? [英] Whats the most concise way to pick a random element by weight in c#?

查看:133
本文介绍了在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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆