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


当前回答

我们可以为List使用扩展方法,并使用线程安全的随机生成器组合。我在NuGet上打包了一个改进的版本,并在GitHub上提供源代码。NuGet版本包含可选的密码强随机。

Pre -。NET 6.0版本:

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Shuffle<T>(this IList<T> list)
{
    if (list == null) throw new ArgumentNullException(nameof(list));
    int n = list.Count;
    while (n > 1)
    {
        int k = ThreadSafeRandom.Instance.Next(n--);
        (list[n], list[k]) = (list[k], list[n]);
    }
}

internal class ThreadSafeRandom
{
    public static Random Instance => _local.Value;

    private static readonly Random _global = new Random();
    private static readonly ThreadLocal<Random> _local = new ThreadLocal<Random>(() =>
    {
        int seed;
        lock (_global)
        {
            seed = _global.Next();
        }
        return new Random(seed);
    });
}

在。net 6.0或更高版本上:

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Shuffle<T>(this IList<T> list)
{
    ArgumentNullException.ThrowIfNull(list);
    int n = list.Count;
    while (n > 1)
    {
        int k = Random.Shared.Next(n--);
        (list[n], list[k]) = (list[k], list[n]);
    }
}

通过NuGet安装库以获得更多功能。

其他回答

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

安装包morelinq

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

我在网上找到了一个有趣的解决办法。

礼貌:https://improveandrepeat.com/2018/08/a-simple-way-to-shuffle-your-lists-in-c/

var shuffled = myList。OrderBy(x => Guid.NewGuid()).ToList();

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

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

IEnumerable扩展方法:

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

肯定是旧帖子,但我只是使用GUID。

Items = Items.OrderBy(o => Guid.NewGuid().ToString()).ToList();

GUID总是唯一的,因为它每次都会重新生成,所以每次结果都会改变。