首页 / .NET / 正文

[.NET/C#]C#中如何随机化一个泛型集合?

2941 发布于: 2018-01-29 读完约需8分钟

问题描述

如题,比如当前有一个泛型集合,在C#开发中,我们使用哪些方式可以让这个泛型集合随机化呢?

方案一

创建一个泛型集合的静态扩展方法,如下:

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;
      }
    }
  }
}

以上方法只是使用了.NET中的System.Random方法来实现一个随机,但它并不是真正意义上的随机,如果你需要真正的实现随机的话,可以使用System.Security.Cryptography命名空间下的RNGCryptoServiceProvider类,如下:

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;
    }
}

调用方式还是和上面一样。

方案二

使用LINQOrderBy方法,结合Guid.NewGuid()方法,如下:

var shuffledcards = cards.OrderBy(a => Guid.NewGuid()).ToList();

方案三

public static IEnumerable<T> Randomize<T>(this IEnumerable<T> source)
{
    Random rnd = new Random();
    return source.OrderBy<T, int>((item) => rnd.Next());
}

方案四

public static IEnumerable<T> Shuffle<T>(
        this IEnumerable<T> source,
        Random generator = null)
{
    if (generator == null)
    {
        generator = new Random();
    }

    var elements = source.ToArray();
    for (var i = elements.Length - 1; i >= 0; i--)
    {
        var swapIndex = generator.Next(i + 1);
        yield return elements[swapIndex];
        elements[swapIndex] = elements[i];
    }
}

版权声明:本作品系原创,版权归码友网所有,如未经许可,禁止任何形式转载,违者必究。

上一篇: [.NET/C#].NET中如何使用反射通过属性名称获取对应的属性值?

下一篇: [.NET/C#]C#中如何对一个可枚举的泛型集合IEnumerable<T>进行动态排序呢?

本文永久链接码友网 » [.NET/C#]C#中如何随机化一个泛型集合?

分享扩散:

发表评论

登录用户才能发表评论, 请 登 录 或者 注册