首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >使用.NET随机化数组的最佳方法

使用.NET随机化数组的最佳方法
EN

Stack Overflow用户
提问于 2008-09-21 01:33:26
回答 16查看 174.2K关注 0票数 164

使用.NET随机化字符串数组的最佳方法是什么?我的数组包含大约500个字符串,我想创建一个新的Array,其中包含相同的字符串,但顺序是随机的。

请在您的答案中包含一个C#示例。

EN

回答 16

Stack Overflow用户

回答已采纳

发布于 2008-09-20 17:40:06

如果你使用的是.NET 3.5,你可以使用下面的IEnumerable coolness:

代码语言:javascript
复制
Random rnd=new Random();
string[] MyRandomArray = MyArray.OrderBy(x => rnd.Next()).ToArray();    

编辑:下面是相应的VB.NET代码:

代码语言:javascript
复制
Dim rnd As New System.Random
Dim MyRandomArray = MyArray.OrderBy(Function() rnd.Next()).ToArray()

第二,为了回应System.Random“不是线程安全的”和“只适用于玩具应用程序”的评论,因为它返回了基于时间的序列:正如我在示例中所使用的,Random()是完全线程安全的,除非您允许重新输入将数组随机化的例程,在这种情况下,您无论如何都需要像lock (MyRandomArray)这样的东西,这样才不会损坏您的数据,这也将保护rnd

此外,应该很好地理解,System.Random作为熵的来源并不是很强。正如MSDN documentation中所指出的,如果您正在做任何与安全相关的事情,那么您应该使用从System.Security.Cryptography.RandomNumberGenerator派生的内容。例如:

代码语言:javascript
复制
using System.Security.Cryptography;

..。

代码语言:javascript
复制
RNGCryptoServiceProvider rnd = new RNGCryptoServiceProvider();
string[] MyRandomArray = MyArray.OrderBy(x => GetNextInt32(rnd)).ToArray();

..。

代码语言:javascript
复制
static int GetNextInt32(RNGCryptoServiceProvider rnd)
    {
        byte[] randomInt = new byte[4];
        rnd.GetBytes(randomInt);
        return Convert.ToInt32(randomInt[0]);
    }
票数 208
EN

Stack Overflow用户

发布于 2008-09-21 08:51:47

下面的实现使用Fisher-Yates algorithm,也就是Knuth Shuffle。它在O(n)时间内运行,并就地洗牌,因此比“按随机排序”技术性能更好,尽管它的代码行更多。有关性能测量的一些比较信息,请参阅here。我已经使用过System.Random,这对于非加密目的来说很好。*

代码语言:javascript
复制
static class RandomExtensions
{
    public static void Shuffle<T> (this Random rng, T[] array)
    {
        int n = array.Length;
        while (n > 1) 
        {
            int k = rng.Next(n--);
            T temp = array[n];
            array[n] = array[k];
            array[k] = temp;
        }
    }
}

用法:

代码语言:javascript
复制
var array = new int[] {1, 2, 3, 4};
var rng = new Random();
rng.Shuffle(array);
rng.Shuffle(array); // different order from first call to Shuffle

*对于更长的数组,为了使(极大的)排列数量相等,有必要对每个交换运行伪随机数生成器(PRNG)多次迭代,以产生足够的熵。对于500个元素的数组,只有500个元素的一小部分!使用PRNG可以获得排列。尽管如此,Fisher-Yates算法是没有偏见的,因此混洗效果将与您使用的RNG一样好。

票数 242
EN

Stack Overflow用户

发布于 2010-08-18 23:45:00

您还可以在Matt Howells之外创建一个扩展方法。举例说明。

代码语言:javascript
复制
   namespace System
    {
        public static class MSSystemExtenstions
        {
            private static Random rng = new Random();
            public static void Shuffle<T>(this T[] array)
            {
                rng = new Random();
                int n = array.Length;
                while (n > 1)
                {
                    int k = rng.Next(n);
                    n--;
                    T temp = array[n];
                    array[n] = array[k];
                    array[k] = temp;
                }
            }
        }
    }

然后你可以像这样使用它:

代码语言:javascript
复制
        string[] names = new string[] {
                "Aaron Moline1", 
                "Aaron Moline2", 
                "Aaron Moline3", 
                "Aaron Moline4", 
                "Aaron Moline5", 
                "Aaron Moline6", 
                "Aaron Moline7", 
                "Aaron Moline8", 
                "Aaron Moline9", 
            };
        names.Shuffle<string>();
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/108819

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档