Int Array Reorder с равномерным распределением в C#? - PullRequest
1 голос
/ 27 января 2020
12,13,14,15,16,19,19,19,19 

до

12,19,13,19,14,19,15,19,16

Привет всем. Может кто-нибудь указать мне подсказки / примеры о том, как распределить первый массив значений Int32, где была добавлена ​​группа из 19 значений, ко второму, где 19 значений довольно равномерно распределены в массиве?

Я не ищу случайного тасования, так как в этом примере # 19 все равно может появляться последовательно, если бы произошла рандомизация. Я хочу убедиться, что # 19 помещен между другими числами в предсказуемой схеме.

Вариант использования этого - что-то вроде команд по очереди, представляющих топи c: команды по 12-16 каждая присутствует один раз, а затем появляется команда # 19, но не должна показывать свои топи c четыре раза подряд, они должны показывать свои топи c между другими командами.

Позже, если двенадцать значений 7 добавляются в массив, тогда они также должны быть равномерно распределены в последовательности, массив будет 21 элементом, но то же правило, что ни # 19, ни # 7 не должны иметь последовательные показы.

Я думал, что в математике может быть что-то. NET библиотека, которая сделает это, но я ничего не нашел. Использование C# on. NET Framework 4.7.

Спасибо.

Ответы [ 3 ]

1 голос
/ 27 января 2020

Вот как это сделать.

var existing = new[] { 12, 13, 14, 15, 16 };
var additional = new [] { 19, 19, 19, 19 };

var lookup =
    additional
        .Select((x, n) => new { x, n })
        .ToLookup(xn => xn.n * existing.Length / additional.Length, xn => xn.x);

var inserted =
    existing
        .SelectMany((x, n) => lookup[n].StartWith(x))
        .ToArray();

Это дает мне такие результаты, как 12, 19, 13, 19, 14, 19, 15, 19, 16.

Единственное, чего не будет делать, это вставить значение в первую позицию , но в противном случае он равномерно распределяет значения.

1 голос
/ 27 января 2020

Подробности о следующем методе, который равномерно (в основном) распределяет дубликаты в вашем списке. Дубликаты могут быть где угодно в вашем списке, они будут распределены.

  1. Создайте словарь всех чисел и отследите, сколько раз они появляются в списке
  2. Используйте новый список без дубликатов. Для каждого числа с дубликатами распределите его по размеру этого нового списка. Каждый раз распределение является четным.
    public static List<int> EvenlyDistribute(List<int> list)
    {
        List<int> original = list;

        Dictionary<int, int> dict = new Dictionary<int, int>();
        list.ForEach(x => dict[x] = dict.Keys.Contains(x) ? dict[x] + 1 : 1);

        list = list.Where(x => dict[x] == 1).ToList();

        foreach (int key in dict.Where(x => x.Value > 1).Select(x => x.Key))
        {
            int iterations = original.Where(x => x == key).Count();
            for (int i = 0; i < iterations; i++)
                list.Insert((int)Math.Ceiling((decimal)((list.Count + iterations) / iterations)) * i, key);
        }

        return list;
    }

Использование в основном:

    List<int> test = new List<int>() {11,11,11,13,14,15,16,17,18,19,19,19,19};
    List<int> newList = EvenlyDistribute(test);

Выход

19,11,13,19,14,11,19,15,16,19,11,17,18
0 голосов
/ 27 января 2020

В случае случайного распределения достаточно следующего кода:

    static void MixArray<T>(T[] array)
    {
        Random random = new Random();

        int n = array.Length;
        while (n > 1)
        {
            n--;
            int k = random.Next(n + 1);
            T value = array[k];
            array[k] = array[n];
            array[n] = value;
        }
    }

Например:

    int[] input = new int[]{12,13,14,15,16,19,19,19,19};
    MixArray<int>(input);

Если вам требуется точное равномерное распределение при сохранении порядка элементов , следующий код будет выполнять работу:

    public static T[] EvenlyDistribute<T>(T[] existing, T[] additional)
    {
        if (additional.Length == 0)
            return existing;

        if (additional.Length > existing.Length) 
        {
            //switch arrays
            T[] temp = additional;
            additional = existing;
            existing = temp;
        }

        T[] result = new T[existing.Length + additional.Length];
        List<int> distribution = new List<int>(additional.Length);
        double ratio = (double)(result.Length-1) / (additional.Length);
        double correction = -1;

        if (additional.Length == 1)
        {
            ratio = (double)result.Length / 2;
            correction = 0;
        }

        double sum = 0;
        for (int i = 0; i < additional.Length; i++)
        {
            sum += ratio;

            distribution.Add(Math.Max(0, (int)(sum+correction)));
        }

        int existing_added = 0;
        int additional_added = 0;
        for (int i = 0; i < result.Length; i++)
        {
            if (additional_added == additional.Length)
                result[i] = existing[existing_added++];
            else
            if (existing_added == existing.Length)
                result[i] = additional[additional_added++];
            else
            {
                if (distribution[additional_added] <= i)
                    result[i] = additional[additional_added++];
                else
                    result[i] = existing[existing_added++];
            }
        }

        return result;
    }

Например:

    int[] existing = new int[] { 12, 13, 14, 15, 16};
    int[] additional = new int[] { 101, 102, 103, 104};

    int[] result = EvenlyDistribute<int>(existing, additional);
    //result = 12, 101, 13, 102, 14, 103, 15, 104, 16
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...