根据百分比从数组列表中选择值 [英] Select value from arraylist based on its percentage

查看:42
本文介绍了根据百分比从数组列表中选择值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我得到了一个对象数组列表.每个对象有 2 个值,contentweight.content 只是一个简单的字符串,而 weight 决定了该字符串使用频率的百分比.

I got an arraylist of objects. Each objects got 2 values, content and weight. content is just a simple string while weight decides the percentage of how often the string should be used.

如果数组中有 2 个对象:

If I have 2 objects in the array:

对象 1:内容:你好重量:20

Object 1: content: hello weight: 20

对象 2:内容:嘿嘿重量:80

Object 2: content: hey weight: 80

第一个对象 content 应该使用 20% 的次数,而第二个对象 content 应该使用 80% 的次数.

First objects content should be used 20% of times while the second objects content should be used 80% of all times.

我将如何根据 weight 决定选择哪些 content?

How would I decide which content gets selected based on the weight?

到目前为止,我得到了以下代码:

I got the following code so far:

foreach (ContentModels cont in match_array)
{
     if (match_array.Count == 1)
     {
         match = cont.content;
         break;
     } 
 }

如果 arraylist 只包含一个对象,它几乎选择第一个 content 但我不知道如果有多个对象怎么办?

which pretty much selects the first content if the arraylist only contains one object but I don't know what do to if there are more than one objects?

推荐答案

好吧,我想在不看别人代码的情况下尝试一下.这是我想出来的.

Alright, I wanted to take a stab at this without looking at someone else's code. Here's what I came up with.

顺便说一句,我希望出错的是 Java 标记而不是 C# 标记:D.

Btw, I hope it was the Java tag that was in error and not the C# tag :D.

这是整个程序.以下是对每一部分的解释

.NET Fiddle

我选择将每个元素作为比例的一部分.因此,在您的示例中,您的总数为 100 (20 + 80),这意味着 20% 的时间应该选择 20 个内容模型.如果您想限制内容模型,使其总权重加起来为 100,则应在创建它们时完成.

I chose to take each element to be a portion in a ratio. Therefore, in your example, your total is 100 (20 + 80) meaning that the 20 content model should get chosen 20% of the time. If you want to constrain your content models such that their total weights add up to 100, that should be done at the time that you create them.

这是我的解决方案.
首先是内容模型:

class ContentModel
{
    public string Content { get; set; }
    public int Weight { get; set; }
}

然后是测试用例列表:

static List<ContentModel> contentOptions = new List<ContentModel>
{
    new ContentModel
    {
        Content = "hello",
        Weight = 20
    },
    new ContentModel
    {
        Content = "hey",
        Weight = 80
    },
    new ContentModel
    {
        Content = "yo dawg",
        Weight = 90
    }
};

鉴于这些测试用例,我们希望看到Hello"出现的概率约为 10.5% (20/(80 + 90 + 20)) * 100.对于其余的测试用例,依此类推.

Given these test cases we would expect to see 'Hello' appear about 10.5% of the time (20 / (80 + 90 + 20)) * 100. And so on for the rest of the test cases.

这是实现这一目标的生成器:

在这里,我们要做的就是弄清楚我们正在处理的总重量是多少.然后我们将选择一个随机数并通过每个模型询问这个数字来自这个内容模型吗?"如果不是,则减去该内容模型的权重并移至下一个,直到我们到达选择 - 权重小于等于的模型.0. 在这种情况下,我们选择了模型.我希望这是有道理的.

Here all we're going to do is figure out what the total weight is that we're working with. Then we're going to pick a random number and go through each model asking "Is this number from this content model?" If no, then subtract that content model's weight and move to the next one until we get to a model where the selection - weight is < 0. In this case we have the model that was chosen. I hope that makes sense.

(注意:我选择每次都重新计算总权重,以防您更改选项的源列表.如果您将该列表设为只读,那么您可以将 .Sum() 调用移到 while 循环之外.)

(Note: I chose to recalculate the total weight every time in case you change the source list of options. If you make that list readonly, then you could move that .Sum() call outside the while loop.)

static IEnumerable<string> GetGreetings()
{
    Random generator = new Random();

    while (true)
    {
        int totalWeight = contentOptions.Sum(x => x.Weight);
        int selection = generator.Next(0, totalWeight);
        foreach (ContentModel model in contentOptions)
        {
            if (selection - model.Weight > 0)
                selection -= model.Weight;
            else
            {
                yield return model.Content;
                break;
            }
        }
     }
}

最后,这里的主要方法也将测试这整个事情:

static void Main(string[] args)
{
    List<string> selectedGreetings = new List<string>();

    /* This will get 1000 greetings, 
     * which are the Content property of the models, group them by the greeting,
     * count them, and then print the count along with the greeting to the Console.
     */
    GetGreetings()
        .Take(1000)
        .GroupBy(x => x)
        .Select(x => new { Count = x.Count(), Content = x.Key })
        .ToList()
        .ForEach(x => Console.WriteLine("{0} : {1}", x.Content, x.Count));

    Console.ReadLine();
}

以下是我的运行结果:

这篇关于根据百分比从数组列表中选择值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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