首页 > C# > 在 C# 中随机化泛型列表顺序的最佳方法是什么?

在 C# 中随机化泛型列表顺序的最佳方法是什么?

上一篇 下一篇

在 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#】栏目查找您需要的精美模板。

相关搜索
  • 下载密码 lanrenmb
  • 下载次数 479次
  • 使用软件 Sublime/Dreamweaver/HBuilder
  • 文件格式 编程语言
  • 文件大小 暂无信息
  • 上传时间 02-21
  • 作者 网友投稿
  • 肖像权 人物画像及字体仅供参考
栏目分类 更多 >
热门推荐 更多 >
微信文章 微信模板 html5 单页式简历模板 企业网站 微信图片 微信素材 自适应 微信公众平台 响应式
您可能会喜欢的其他模板