Генератор случайных чисел в C# - уникальные значения

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

Дополнительная информация:
Значение Max: 100
Число элементов: 100

ВАЖНЫЙ РАБОТАЙТЕ ДАЛЕЕ НАД МОЕЙ ИДЕЕЙ

моя идея

public void FillArray(int[] A, int Range)
{
    for (int I = 0; I < A.Length; I++)
    {
        A[I] = ValidNumber(T, I, Range);
    }
} /* Fill Array */

Реализация вида выбора

public void SelectionSort(int[] A)
{
    int K, X;
    for (int I = 0; I < A.Length - 1; I++)
    {
        K = I;
        X = A[K];
        for (int J = I + 1; J < A.Length; J++)
        {
            if (A[J] < X)
            {
                K = J;
                X = A[K];
            }
        }
        A[K] = A[I];
        A[I] = X;
    }
} /* Selection sort */

Это просто некоторые идеи теперь, я хочу знать, как я могу зафиксировать его так, я могу посмотреть с видом выбора, если существует allread там (fillarray), который является, то же раз так заменяет его новым случайным значением. И таким образом, я хочу создать случайный массив с ints - от 1 до 100 в произвольном порядке

7
задан djdy 26 September 2012 в 00:32
поделиться

5 ответов

Следующий код будет генерировать массив с числами от 1 до 100 в случайном порядке.

    Random rnd = new Random();
    var randomNumbers = Enumerable.Range(1, 100).OrderBy(i => rnd.Next()).ToArray();
7
ответ дан 6 December 2019 в 04:56
поделиться

Из вашего описания я понимаю, что вам нужен массив из 100 целых чисел со значениями от 1 до 100 и без повторяющихся чисел. Если числа являются целыми числами, вам не нужно генерировать случайные числа, поскольку все возможные числа находятся в массиве. Следовательно, рандомизировать можно только порядок или числа.

Используя подход Linq и Джеспера Палма - с помощью Томаса Левеска следующий оператор даст вам нужный массив.

Random rnd = new Random();
var randomNumbers = Enumerable.Range(1, 100)
                              .Select(x => new { val = x, order = rnd.Next() })
                              .OrderBy(i => i.order)
                              .Select(x => x.val)
                              .ToArray();

Этот метод даже довольно быстрый, определенно более эффективный, чем любые операции сравнения.

Чтобы объяснить вышеперечисленное оригинальному плакату, см. Комментарий ниже:

  • Enumerable.Range (1, 100) создает диапазон целых чисел, начиная с 1 и заканчивая 100.
  • .Select (x => new {val = x, order = rnd.Next ()}) создает новый временный объект, содержащий значение и позицию заказа, которая определяется случайным числом.
  • .OrderBy (i => i.order) сортирует временные объекты по их порядковой позиции.
  • .Выберите (x => x.val) выбирает значение временного объекта, тем самым преобразуя его обратно в int.
  • .ToArray () снова превращает все обратно в массив.

Используемый синтаксис - LINQ, доступный в .NET 3.5. В более старых версиях вам придется реализовать это самостоятельно, что намного сложнее и намного дольше.

После комментария Эрика: Если требуется перетасовка, вы можете ввести следующий код

var list = myInputList;
var result = list.Select(x => new { val = x, order = rnd.Next() })
                 .OrderBy(i => i.order)
                 .Select(x => x.val)
                 .ToArray();
5
ответ дан 6 December 2019 в 04:56
поделиться

Вот наивная реализация:

int[] values = new int[100];
Random random = new Random();
for(int i = 0; i < values.Length; i++)
{
    int v;
    do
    {
        v = random.Next(100) + 1;
    } while (Array.IndexOf(values, v) != -1)
    values[i] = v;
}

Но это было бы довольно неэффективно, особенно ближе к концу массива ...

Лучшее решение было бы следует учитывать, что, поскольку вам нужно 100 различных значений от 1 до 100 в случайном порядке, ваш массив в конечном итоге будет содержать все возможные значения от 1 до 100. Поэтому вам просто нужно сгенерировать последовательность этих значений и "перемешать" ее :

int[] values = Enumerable.Range(1, 100).ToArray();
Random random = new Random();
for(int i = values.Length - 1; i > 0; i--)
{
    int j = random.Next(i + 1);
    int tmp = values[i];
    values[i] = values[j];
    values[j] = tmp;
}

РЕДАКТИРОВАТЬ: лучший подход, который должен работать для менее конкретных случаев:

T[] RandomCombinationWithNoRepeat<T>(IEnumerable<T> itemsToPickFrom, int numberOfItemsToPick)
{
    // Copy original items to pick from, because we need to modify it
    List<T> itemsCopy = new List<T>(itemsToPickFrom);
    T[] array = new T[numberOfItemsToPick];
    Random random = new Random();
    for(int i = 0; i < numberOfItemsToPick; i++)
    {
        // Pick item and remove it from list
        int index = random.Next(itemsCopy.Count);
        array[i] = itemsCopy[index];
        itemsCopy.RemoveAt(index);
    }
    return array;
}

В вашем случае вы бы использовали его так:

int[] result = RandomCombinationWithNoRepeat(Enumerable.Range(1, 100), 100);
2
ответ дан 6 December 2019 в 04:56
поделиться

как мне это сделать, чтобы я мог проверить, есть ли уже значение в массиве, и если да, сгенерировать новое значение

Вы не Я никогда не делаю этого, потому что это очень плохая идея .

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

  1. Выберите число от одного до миллиона.
  2. Проверьте, есть ли он уже в списке.
  3. Если да, вернитесь к шагу 1
  4. В противном случае добавьте номер в список.
  5. Есть ли в списке миллион пунктов? Если да, то все готово. Если нет, вернитесь к шагу 1.

Очевидно, это работает. Это хорошая идея? Предположим, вы почти закончили. В списке 999999 пунктов. Единственный недостающий элемент - 857313. Что вы делаете? Вы выбираете случайное число, скажем, 12. Теперь вы проверяете 999999 пунктов в списке, чтобы узнать, 12 ли среди них.12 могло быть одним из первых чисел, которые вы выбрали, поэтому его можно будет быстро найти. Или он может быть одним из последних, поэтому на это уйдет много времени. В среднем требуется 500000 проверок, чтобы увидеть, 12 ли в списке. И это так, поскольку в списке отсутствует только один номер.

12 не сложилось. Вернитесь к началу. Выберите другое случайное число, скажем, 53259. Это есть в списке? Еще полмиллиона чеков.

Продолжайте делать это, пока не сгенерируете 857313, что происходит один раз на миллион попыток.

Таким образом, в среднем, чтобы поместить последний элемент в список, требуется 500000 x 1000000 = пятьсот миллиардов сравнений. Может потребоваться гораздо больше. Может потребоваться несколько триллионов сравнений. Или вам может повезти, и для этого потребуется один. Но в среднем полтриллиона сравнений.

Это ужасный способ произвольного упорядочивания списка.

Есть два хороших способа упорядочить список в случайном порядке.

(1) Создайте устройство, которое может сортировать список с учетом функции упорядочивания. Обеспечьте стабильный порядок, основанный на случайном начальном значении.

Обратите внимание, что вы должны не производить случайное упорядочение, создавая метод, который возвращает случайные результаты, когда его спрашивают «больше ли A, чем B?» Это нестабильный порядок; многие алгоритмы сортировки основаны на стабильном порядке сортировки и переходят в бесконечные циклы или имеют другое плохое поведение при нестабильном порядке сортировки.

Этот алгоритм имеет размер O (n lg n) и обладает тем приятным свойством, что, как показывают другие ответы, его очень легко записывать из стандартных частей.Это также очень быстро для небольших списков в типичных реализациях.

(2) Выбрать элемент по индексу из исходного списка случайным образом, удаляя его из исходного списка по мере продвижения и помещая в список назначения.

Последний известен как Knuth Shuffle или Fischer-Yates Shuffle, и это очень быстрый алгоритм.Вы можете сделать это «на месте», преобразовав существующий массив в перетасованный порядок или создав новый список. У него также есть приятное свойство, что вы можете «платить за игру», перетасовывая «верхнюю часть» списка по мере необходимости. Если у вас есть миллион элементов, которые нужно перемешать, но вам нужна только первая сотня, вы можете просто определить порядок сортировки для первой сотни и назвать это хорошим.

30
ответ дан 6 December 2019 в 04:56
поделиться

насколько я понимаю. Вам нужен набор целых чисел со случайными числами. Я предполагаю, что использование массива int или List of int не имеет значения. Вот простой полный подход, который вы описали.
с использованием System; с использованием System.Collections .Generic; using System.Text;

пространство имен FillRandom { класс Program { static void Main (string [] args ) { int minValue = 1; int maxValue = 100; // создаем список int с емкостью 100 List array = new List (100);

        FillArray(array, minValue, maxValue, array.Capacity);

        //print out all values in the array
        foreach (int i in array)
        {
            Console.WriteLine(i);
        }
    }

    private static void FillArray(List<int> array, int minValue, int maxValue, int capacity)
    {
        int count = 0;
        while (array.Count != capacity - 1)
        {
            Random rnd = new Random();
            int value = rnd.Next(minValue, maxValue);
            if (!array.Contains(value))
            {
                array.Add(value);
            }
            count++;
        }
        //print out the number of times the looping occurs
        Console.WriteLine("count: "+count);
    }        
}

}

Вы можете создать консольный проект и попробовать.

0
ответ дан 6 December 2019 в 04:56
поделиться
Другие вопросы по тегам:

Похожие вопросы: