生成随机的唯一值 C#

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14473321/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 11:56:13  来源:igfitidea点击:

Generating random, unique values C#

c#.netrandomunique

提问by Christian Peut

I've searched for a while and been struggling to find this, I'm trying to generate several random, unique numbers is C#. I'm using System.Random, and I'm using a DateTime.Now.Ticksseed:

我已经搜索了一段时间并且一直在努力找到这个,我正在尝试生成几个随机的、唯一的数字是 C#。我正在使用System.Random,我正在使用DateTime.Now.Ticks种子:

public Random a = new Random(DateTime.Now.Ticks.GetHashCode());
private void NewNumber()
{
    MyNumber = a.Next(0, 10);
}

I'm calling NewNumber()regularly, but the problem is I often get repeated numbers. Some people suggested because I was declaring the random every time I did it, it would not produce a random number, so I put the declaration outside my function. Any suggestions or better ways than using System.Random? Thank you

NewNumber()经常打电话,但问题是我经常收到重复的号码。有人建议,因为我每次都声明随机数,它不会产生随机数,所以我把声明放在我的函数之外。有什么建议或比使用更好的方法System.Random吗?谢谢

采纳答案by Habib

I'm calling NewNumber() regularly, but the problem is I often get repeated numbers.

我经常打电话给 NewNumber(),但问题是我经常收到重复的数字。

Random.Nextdoesn't guarntee the number to be unique. Also your range is from 0 to 10 and chances are you will get duplicate values. May be you can setup a list of intand insert random numbers in the list after checking if it doesn't contain the duplicate. Something like:

Random.Next不保证号码是唯一的。此外,您的范围是从 0 到 10,您可能会得到重复的值。可能您可以设置一个列表int并在检查它是否不包含重复项后在列表中插入随机数。就像是:

public Random a = new Random(); // replace from new Random(DateTime.Now.Ticks.GetHashCode());
                                // Since similar code is done in default constructor internally
public List<int> randomList = new List<int>();
int MyNumber = 0;
private void NewNumber()
{
    MyNumber = a.Next(0, 10);
    if (!randomList.Contains(MyNumber))
        randomList.Add(MyNumber);
}

回答by itsme86

You might try shuffling an array of possible ints if your range is only 0 through 9. This adds the benefit of avoiding any conflicts in the number generation.

如果您的范围只有 0 到 9,您可以尝试对可能的整数数组进行混洗。这增加了避免数字生成中发生任何冲突的好处。

var nums = Enumerable.Range(0, 10).ToArray();
var rnd = new Random();

// Shuffle the array
for (int i = 0;i < nums.Length;++i)
{
    int randomIndex = rnd.Next(nums.Length);
    int temp = nums[randomIndex];
    nums[randomIndex] = nums[i];
    nums[i] = temp;
}

// Now your array is randomized and you can simply print them in order
for (int i = 0;i < nums.Length;++i)
    Console.WriteLine(nums[i]);

回答by Andrew Savinykh

Depending on what you are really after you can do something like this:

根据您的实际情况,您可以执行以下操作:

using System;
using System.Collections.Generic;
using System.Linq;

namespace SO14473321
{
    class Program
    {
        static void Main()
        {
            UniqueRandom u = new UniqueRandom(Enumerable.Range(1,10));
            for (int i = 0; i < 10; i++)
            {
                Console.Write("{0} ",u.Next());
            }
        }
    }

    class UniqueRandom
    {
        private readonly List<int> _currentList;
        private readonly Random _random = new Random();

        public UniqueRandom(IEnumerable<int> seed)
        {
            _currentList = new List<int>(seed);
        }

        public int Next()
        {
            if (_currentList.Count == 0)
            {
                throw new ApplicationException("No more numbers");
            }

            int i = _random.Next(_currentList.Count);
            int result = _currentList[i];
            _currentList.RemoveAt(i);
            return result;
        }
    }
}

回答by Matthew Watson

I'm posting a correct implementation of a shuffle algorithm, since the other one posted here doesn't produce a uniform shuffle.

我发布了 shuffle 算法的正确实现,因为这里发布的另一个不会产生统一的 shuffle。

As the other answer states, for small numbers of values to be randomized, you can simply fill an array with those values, shuffle the array, and then use however many of the values that you want.

正如另一个答案所述,对于要随机化的少量值,您可以简单地用这些值填充一个数组,对数组进行混洗,然后使用您想要的任意多个值。

The following is an implementation of the Fisher-Yates Shuffle(aka the Knuth Shuffle). (Read the "implementation errors" section of that link (search for "always selecting j from the entire range of valid array indices on every iteration") to see some discussion about what is wrong with the other implementation posted here.)

以下是Fisher-Yates Shuffle(又名 Knuth Shuffle)的实现。(阅读该链接的“实现错误”部分(搜索“每次迭代时始终从有效数组索引的整个范围中选择 j”)以查看有关此处发布的其他实现有什么问题的一些讨论。)

using System;
using System.Collections.Generic;

namespace ConsoleApplication2
{
    static class Program
    {
        static void Main(string[] args)
        {
            Shuffler shuffler = new Shuffler();
            List<int> list = new List<int>{ 1, 2, 3, 4, 5, 6, 7, 8, 9 };
            shuffler.Shuffle(list);

            foreach (int value in list)
            {
                Console.WriteLine(value);
            }
        }
    }

    /// <summary>Used to shuffle collections.</summary>

    public class Shuffler
    {
        /// <summary>Creates the shuffler with a <see cref="MersenneTwister"/> as the random number generator.</summary>

        public Shuffler()
        {
            _rng = new Random();
        }

        /// <summary>Shuffles the specified array.</summary>
        /// <typeparam name="T">The type of the array elements.</typeparam>
        /// <param name="array">The array to shuffle.</param>

        public void Shuffle<T>(IList<T> array)
        {
            for (int n = array.Count; n > 1; )
            {
                int k = _rng.Next(n);
                --n;
                T temp = array[n];
                array[n] = array[k];
                array[k] = temp;
            }
        }

        private System.Random _rng;
    }
}

回答by Herman Vercuiel

You could also use a dataTable storing each random value, then simply perform the random method while != values in the dataColumn

您还可以使用存储每个随机值的数据表,然后简单地执行随机方法而 != 数据列中的值

回答by JOSEFtw

NOTE, I dont recommend this :).Here's a "oneliner" as well:

注意,我不推荐这个:)。这里还有一个“oneliner”:

//This code generates numbers between 1 - 100 and then takes 10 of them.
var result = Enumerable.Range(1,101).OrderBy(g => Guid.NewGuid()).Take(10).ToArray();

回答by Arsalan

Try this:

尝试这个:

private void NewNumber()
  {
     Random a = new Random(Guid.newGuid().GetHashCode());
     MyNumber = a.Next(0, 10);
  }

Some Explnations:

一些解释:

Guid: base on here: Represents a globally unique identifier (GUID)

Guid:基于这里: 代表一个全局唯一标识符 (GUID)

Guid.newGuid()produces a unique identifier like "936DA01F-9ABD-4d9d-80C7-02AF85C822A8"

Guid.newGuid()产生一个唯一的标识符,如 "936DA01F-9ABD-4d9d-80C7-02AF85C822A8"

and it will be unique in all over the universe base on here

它会在所有是唯一的在宇宙中的位置基地

Hash code hereproduce a unique integer from our unique identifier

此处的哈希码根据我们的唯一标识符生成唯一整数

so Guid.newGuid().GetHashCode()gives us a unique number and the random class will produce real random numbers throw this

所以Guid.newGuid().GetHashCode()给了我们一个唯一的数字,随机类将产生真正的随机数抛出这个

Sample: https://rextester.com/ODOXS63244

示例:https: //rextester.com/ODOXS63244

generated ten random numbers with this approach with result of:

用这种方法生成了十个随机数,结果为:

-1541116401
7
-1936409663
3
-804754459
8
1403945863
3
1287118327
1
2112146189
1
1461188435
9
-752742620
4
-175247185
4
1666734552
7

we got two 1s next to each other, but the hash codes do not same.

我们有两个1相邻的 s,但哈希码不相同。

回答by Vasily Novsky

And here my version of finding N random unique numbers using HashSet. Looks pretty simple, since HashSet can contain only different items. It's interesting - would it be faster then using List or Shuffler?

在这里,我使用HashSet查找 N 个随机唯一数字的版本。看起来很简单,因为 HashSet 只能包含不同的项目。很有趣 - 使用 List 或 Shuffler 会更快吗?

using System;
using System.Collections.Generic;

namespace ConsoleApplication1
{
    class RnDHash
    {
        static void Main()
        {
            HashSet<int> rndIndexes = new HashSet<int>();
            Random rng = new Random();
            int maxNumber;
            Console.Write("Please input Max number: ");
            maxNumber = int.Parse(Console.ReadLine());
            int iter = 0;
            while (rndIndexes.Count != maxNumber)
            {
                int index = rng.Next(maxNumber);
                rndIndexes.Add(index);
                iter++;
            }
            Console.WriteLine("Random numbers were found in {0} iterations: ", iter);
            foreach (int num in rndIndexes)
            {
                Console.WriteLine(num);
            }
            Console.ReadKey();
        }
    }
}

回答by FELIXKIPRONO

You can use basic Random Functions of C#

您可以使用 C# 的基本随机函数

Random ran = new Random();
int randomno = ran.Next(0,100);

you can now use the value in the randomno in anything you want but keep in mind that this will generate a random number between 0and 100Only and you can extend that to any figure.

您现在可以在您想要的任何内容中使用 randomno 中的值,但请记住,这将在0100Only之间生成一个随机数,您可以将其扩展到任何数字。

回答by Evren Ozturk

This is a unity only answer:

这是一个统一的答案:

Check this ready-to-use method: Give in a range & count of number you want to get.

检查这个即用型方法:给出您想要获得的数字的范围和数量。

public static int[] getUniqueRandomArray(int min, int max, int count) {
    int[] result = new int[count];
    List<int> numbersInOrder = new List<int>();
    for (var x = min; x < max; x++) {
        numbersInOrder.Add(x);
    }
    for (var x = 0; x < count; x++) {
        var randomIndex = UnityEngine.Random.Range(0, numbersInOrder.Count);
        result[x] = numbersInOrder[randomIndex];
        numbersInOrder.RemoveAt(randomIndex);
    }

    return result;
}