.jpg)
在 C# 中随机化泛型列表顺序的最佳方法是什么?我在一个列表中有一组有限的 75 个数字,我想分配一个随机顺序,以便为彩票类型的应用程序绘制它们。

网友回答:
如果我们只需要以完全随机的顺序对项目进行随机排序(只是为了混合列表中的项目),我更喜欢这个简单而有效的代码,它按 guid 对项目进行排序……
var shuffledcards = cards.OrderBy(a => Guid.NewGuid()).ToList();
正如人们在评论中指出的那样,GUID 不能保证是随机的,因此我们应该改用真正的随机数生成器:
private static Random rng = new Random();
...
var shuffledcards = cards.OrderBy(a => rng.Next()).ToList();

网友回答:
使用基于 Fisher-Yates shuffle 的扩展方法随机播放任何内容:(I)List
private static Random rng = new Random();
public static void Shuffle<T>(this IList<T> list)
{
int n = list.Count;
while (n > 1) {
n--;
int k = rng.Next(n + 1);
T value = list[k];
list[k] = list[n];
list[n] = value;
}
}
用法:
List<Product> products = GetProducts();
products.Shuffle();
上面的代码使用备受批评的System.Random方法来选择交换候选者。它很快,但不像应有的那样随机。如果你在随机播放中需要更好的随机性质量,请使用System.Security.Cryptography中的随机数生成器,如下所示:
using System.Security.Cryptography;
...
public static void Shuffle<T>(this IList<T> list)
{
RNGCryptoServiceProvider provider = new RNGCryptoServiceProvider();
int n = list.Count;
while (n > 1)
{
byte[] box = new byte[1];
do provider.GetBytes(box);
while (!(box[0] < n * (Byte.MaxValue / n)));
int k = (box[0] % n);
n--;
T value = list[k];
list[k] = list[n];
list[n] = value;
}
}
一个简单的比较可以在这个博客(WayBack Machine)上找到。
编辑:自从几年前写了这个答案以来,很多人评论或写信给我,指出我比较中的大愚蠢缺陷。他们当然是对的。System.Random如果按照预期的方式使用,那就没有错了。在上面的第一个例子中,我在 Shuffle 方法中实例化了 rng 变量,如果要重复调用该方法,它会带来麻烦。下面是一个固定的完整示例,基于今天从 SO 这里收到的@weston非常有用的评论。
课程.cs:
using System;
using System.Collections.Generic;
using System.Threading;
namespace SimpleLottery
{
class Program
{
private static void Main(string[] args)
{
var numbers = new List<int>(Enumerable.Range(1, 75));
numbers.Shuffle();
Console.WriteLine("The winning numbers are: {0}", string.Join(", ", numbers.GetRange(0, 5)));
}
}
public static class ThreadSafeRandom
{
[ThreadStatic] private static Random Local;
public static Random ThisThreadsRandom
{
get { return Local ?? (Local = new Random(unchecked(Environment.TickCount * 31 + Thread.CurrentThread.ManagedThreadId))); }
}
}
static class MyExtensions
{
public static void Shuffle<T>(this IList<T> list)
{
int n = list.Count;
while (n > 1)
{
n--;
int k = ThreadSafeRandom.ThisThreadsRandom.Next(n + 1);
T value = list[k];
list[k] = list[n];
list[n] = value;
}
}
}
}

网友回答:
我对这个简单算法的所有笨拙版本感到有些惊讶。Fisher-Yates(或Knuth shuffle)有点棘手,但非常紧凑。为什么很棘手?因为您需要注意您的随机数生成器返回的值是包含的还是排除的。我还编辑了维基百科的描述,这样人们就不会盲目地遵循那里的伪代码并创建难以检测的错误。对于 .Net,返回不包含 so 的数字,事不宜迟,以下是在 C#/.Net 中实现它的方法:r(a,b)bRandom.Next(a,b)b
public static void Shuffle<T>(this IList<T> list, Random rnd)
{
for(var i=list.Count; i > 0; i--)
list.Swap(0, rnd.Next(0, i));
}
public static void Swap<T>(this IList<T> list, int i, int j)
{
var temp = list[i];
list[i] = list[j];
list[j] = temp;
}
试试这段代码。
模板简介:该模板名称为【在 C# 中随机化泛型列表顺序的最佳方法是什么?】,大小是暂无信息,文档格式为.编程语言,推荐使用Sublime/Dreamweaver/HBuilder打开,作品中的图片,文字等数据均可修改,图片请在作品中选中图片替换即可,文字修改直接点击文字修改即可,您也可以新增或修改作品中的内容,该模板来自用户分享,如有侵权行为请联系网站客服处理。欢迎来懒人模板【C#】栏目查找您需要的精美模板。