下面摘录洗牌号码,并在每执行改变号码的顺序:随机数和生成数字的相同顺序在每个执行
Enumerable.Range(1, 1000).OrderBy(r => Guid.NewGuid()).ToList();
,但我想洗牌的数字和在每次执行生成号码相同的序列应用?
下面摘录洗牌号码,并在每执行改变号码的顺序:随机数和生成数字的相同顺序在每个执行
Enumerable.Range(1, 1000).OrderBy(r => Guid.NewGuid()).ToList();
,但我想洗牌的数字和在每次执行生成号码相同的序列应用?
使用像Fisher-Yates shuffle这样的算法对项目进行重新排序会更高效。 OrderBy
的运行时复杂度为O(N log N)
,而Fisher-Yates shuffle为O(N)
。
此外,为了提供随机数,您应该使用Random
类,而不是Guid.NewGuid
,它提供了完全不同的用途,并且恰好创建了随机(成本更高)的东西。
我更愿意执行洗牌作为扩展方法:
public static class ListExtensions
{
public static IList<T> Shuffle<T>(this IList<T> list, Random random)
{
for (var i = list.Count; i > 1; i -= 1)
{
var j = random.Next(i);
var temp = list[j];
list[j] = list[i - 1];
list[i - 1] = temp;
}
return list;
}
}
可以通过提供一个Random
实例与种子特异性(在这种情况下为0)达到所期望的结果。这将确保每次执行代码时产生的随机数序列是相同的:
var shuffledList = Enumerable.Range(0, 1000).ToList().Shuffle(new Random(0));
不错!我发誓我在我的小扩展库中有完全相同的代码。 – itsme86
这是不是破坏了随机排列数字的目的? – Amy
生成一次并硬编码结果。或者使用'Enumerable.Range(1,1000).ToArray()'。这是一个合理的,尽管不太可能的随机排序。 –
请勿使用GUID进行随机播放。使用Random对象进行混洗并使用相同的种子初始化对象。 – itsme86