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

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

问题描述

我有一个对象数组列表.每个对象都有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小提琴

我选择将每个元素都按比例分配.因此,在您的示例中,总数为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.

所以这是我的解决方法.
首先是内容模型:

So here's my solution.
First the content models:

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天全站免登陆