Как мне создать правило для более чем одного варианта в Bogus?

У меня есть правило выбирать вариант наугад:

    .RuleFor(c=>field, x=>x.PickRandom("Option1", "Option2", "Option3", "Option4"))

Используя значение по умолчанию, я могу изменить вероятность одного из элементов. Я хотел бы установить вероятности всех четырех пунктов. Вариант 1 будет выбран в 50% случаев, Вариант 2 будет выбран в 30%, затем 15% для Варианта 3 и 5% для Варианта 4.

Я хотел бы использовать WeightedRandom:

    .RuleFor(c=>field, x=>PickWeightedRandom(valueArray, weightArray)

Нет такого метода, как PickWeightedRandom, но WeightedRandom - это метод в классе Randomizer. Как заставить работать WeightedRandom?

РЕДАКТИРОВАТЬ: Может быть, метод расширения?


person Cakemeister    schedule 21.01.2021    source источник


Ответы (2)


Кажется, работает следующее:

void Main()
{
   var items = new []{"kiwi", "orange", "cherry", "apple"};
   var weights = new[]{0.1f, 0.1f, 0.2f, 0.6f};
   
   var faveFaker = new Faker<Favorite>()
      .RuleFor(x => x.Fruit, f => f.Random.WeightedRandom(items, weights));
      
   faveFaker.Generate(10).Dump();
}

public class Favorite
{
   public string Fruit {get;set;}
}

введите описание изображения здесь


Конечно, использование методов расширения C # - всегда отличный способ расширить Bogus, чтобы он наилучшим образом соответствовал вашим потребностям API:

void Main()
{  
   var faveFaker = new Faker<Favorite>()
      .RuleFor(x => x.Fruit, f => f.WeightedRandom( ("kiwi",   0.1f), ("orange", 0.1f),
                                                    ("cherry", 0.2f), ("apple",  0.6f)) );
      
   faveFaker.Generate(10).Dump();
}

public class Favorite
{
   public string Fruit {get;set;}
}

public static class MyExtensionsForBogus
{
   public static T WeightedRandom<T>(this Faker f, params (T item, float weight)[] items)
   {
      var weights = items.Select(i => i.weight).ToArray();
      var choices = items.Select(i => i.item).ToArray();
      return f.Random.WeightedRandom(choices, weights);
   }
}

введите описание изображения здесь

person Brian Chavez    schedule 22.01.2021

Один из ответов - выбрать случайную строку в другом месте, а затем использовать оператор = ›, чтобы указать на результат.

    public static string PickAString(string[] items, float[] weights)
    {
        // hopefully all the weights will add up to 1. If not, this method may throw for array out of bounds.
        // Also, it would be best if the number of items in each array is the same, to prevent out of bounds exception.

        // generate a number from 0 to less than 1
        double randomValue = random.NextDouble();
        double weightSum = 0;
        for (int i = 0; i < items.Length; i++)
        {
            weightSum += weights[i];
            if (randomValue < weightSum)
                return items[i];
        }
        return null; // if the weights don't add up.
    }

    .RuleFor(c => c.field, _ =>
    { 
        return PickAString(values, weights); 
    }) 

Это работает, но было бы более элегантно добавить это в библиотеку.

person Cakemeister    schedule 21.01.2021