• LINQ中使用Shuffle方法将集合中的元素重新随机洗牌
  • 发布于 1个月前
  • 108 热度
    0 评论
前言

dotnet 10 中引入了一个新的 LINQ 方法 Shuffle 可以将一个集合中的元素随机洗牌返回,今天我们详细了解下。


新API
新引入的 API 定义如下:
namespace System.Linq;
publicstaticclassEnumerable
{
    publicstatic IEnumerable<T> Shuffle<T>(this IEnumerable<T> source) { }
}
publicstaticclassAsyncEnumerable
{
    publicstatic IAsyncEnumerable<T> Shuffle<T>(this IAsyncEnumerable<T> source) { }
}
publicstaticclassQueryable
{
    publicstatic IQueryable<T> Shuffle<T>(this IQueryable<T> source) { }
}
例子
// 堆代码 duidaima.com
var source = Enumerable.Range(1, 5).ToArray();
Console.WriteLine(string.Join(",", source));
source.Shuffle();
Console.WriteLine(string.Join(",", source));
大家可以先猜一下输出结果会是什么,输出结果如下:

从上面的输出结果可以看得出来,原来的数组 source 中的元素并未改变,这是因为 Shuffle 方法并不会改变原有数组,而是返回一个新的 IEnumerable 对象
我们再来做一些测试,看看返回的数据,测试代码如下:
var source = Enumerable.Range(1, 5).ToArray();
Console.WriteLine(string.Join(",", source.Shuffle()));
Console.WriteLine(string.Join(",", source.Shuffle().Take(3)));
Console.WriteLine(string.Join(",", source.Shuffle().Take(3)));
Console.WriteLine(string.Join(",", source.Shuffle().Take(6)));
输出结果如下:

那么如果是同一个 Shuffle 返回值,两次会不会一样呢,我们也来做一个测试
var source = Enumerable.Range(1, 5).ToArray();
var shuffled = source.Shuffle();
Console.WriteLine(string.Join(",", shuffled));
Console.WriteLine(string.Join(",", shuffled));
输出结果如下:

可以看到即使是同一个 shuffle 返回值的对象,每次使用时也不相同,实际数据的填充是遍历时获取的,并不是提前生成好的,确定的。如果需要对数组进行重排可以使用 .NET 8 引入的 Random.Shuffle 方法,使用示例如下:
Console.WriteLine("Random.Shared.Shuffle(array) sample");
var array = Enumerable.Range(1, 10).ToArray();
Console.WriteLine(string.Join(",", array));
Random.Shared.Shuffle(array);
Console.WriteLine(string.Join(",", array));
输出结果如下:

参考信息
https://github.com/dotnet/runtime/issues/111221
https://github.com/dotnet/runtime/pull/112173
https://github.com/dotnet/runtime/issues/73864
用户评论