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


当前回答

您可以使用这个简单的扩展方法来实现这一点

public static class IEnumerableExtensions
{

    public static IEnumerable<t> Randomize<t>(this IEnumerable<t> target)
    {
        Random r = new Random();

        return target.OrderBy(x=>(r.Next()));
    }        
}

你可以通过下面的步骤来使用它

// use this on any collection that implements IEnumerable!
// List, Array, HashSet, Collection, etc

List<string> myList = new List<string> { "hello", "random", "world", "foo", "bar", "bat", "baz" };

foreach (string s in myList.Randomize())
{
    Console.WriteLine(s);
}

其他回答

    public static List<T> Randomize<T>(List<T> list)
    {
        List<T> randomizedList = new List<T>();
        Random rnd = new Random();
        while (list.Count > 0)
        {
            int index = rnd.Next(0, list.Count); //pick a random item from the master list
            randomizedList.Add(list[index]); //place it at the end of the randomized list
            list.RemoveAt(index);
        }
        return randomizedList;
    }

如果我们只需要以完全随机的顺序洗牌项目(只是在一个列表中混合项目),我更喜欢这个简单而有效的代码,按guid排序项目…

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

正如人们在评论中指出的那样,guid不能保证是随机的,所以我们应该使用真正的随机数生成器:

private static Random rng = new Random();
...
var shuffledcards = cards.OrderBy(a => rng.Next()).ToList();

可以使用morelinq包中的Shuffle扩展方法,它适用于IEnumerables

安装包morelinq

using MoreLinq;
...    
var randomized = list.Shuffle();

这里有一个线程安全的方法来做到这一点:

public static class EnumerableExtension
{
    private static Random globalRng = new Random();

    [ThreadStatic]
    private static Random _rng;

    private static Random rng 
    {
        get
        {
            if (_rng == null)
            {
                int seed;
                lock (globalRng)
                {
                    seed = globalRng.Next();
                }
                _rng = new Random(seed);
             }
             return _rng;
         }
    }

    public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> items)
    {
        return items.OrderBy (i => rng.Next());
    }
}

想法是获得匿名对象的项目和随机顺序,然后按此顺序重新排序项目,并返回值:

var result = items.Select(x => new { value = x, order = rnd.Next() })
            .OrderBy(x => x.order).Select(x => x.value).ToList()