在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安装库以获得更多功能。

其他回答

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

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

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

对已接受答案的简单修改,返回一个新的列表,而不是原地工作,并像许多其他Linq方法一样接受更通用的IEnumerable<T>。

private static Random rng = new Random();

/// <summary>
/// Returns a new list where the elements are randomly shuffled.
/// Based on the Fisher-Yates shuffle, which has O(n) complexity.
/// </summary>
public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> list) {
    var source = list.ToList();
    int n = source.Count;
    var shuffled = new List<T>(n);
    shuffled.AddRange(source);
    while (n > 1) {
        n--;
        int k = rng.Next(n + 1);
        T value = shuffled[k];
        shuffled[k] = shuffled[n];
        shuffled[n] = value;
    }
    return shuffled;
}
private List<GameObject> ShuffleList(List<GameObject> ActualList) {


    List<GameObject> newList = ActualList;
    List<GameObject> outList = new List<GameObject>();

    int count = newList.Count;

    while (newList.Count > 0) {

        int rando = Random.Range(0, newList.Count);

        outList.Add(newList[rando]);

        newList.RemoveAt(rando);

     

    }

    return (outList);

}

用法:

List<GameObject> GetShuffle = ShuffleList(ActualList);

如果您有一个固定的数字(75),您可以创建一个包含75个元素的数组,然后枚举您的列表,将元素移动到数组中的随机位置。您可以使用Fisher-Yates shuffle生成列表号到数组索引的映射。

解决这类问题的一个非常简单的方法是在列表中使用一些随机的元素交换。

在伪代码中是这样的:

do 
    r1 = randomPositionInList()
    r2 = randomPositionInList()
    swap elements at index r1 and index r2 
for a certain number of times