2017-06-12 36 views
0

下面摘录洗牌号码,并在每执行改变号码的顺序:随机数和生成数字的相同顺序在每个执行

Enumerable.Range(1, 1000).OrderBy(r => Guid.NewGuid()).ToList(); 

,但我想洗牌的数字和在每次执行生成号码相同的序列应用?

+5

这是不是破坏了随机排列数字的目的? – Amy

+0

生成一次并硬编码结果。或者使用'Enumerable.Range(1,1000).ToArray()'。这是一个合理的,尽管不太可能的随机排序。 –

+2

请勿使用GUID进行随机播放。使用Random对象进行混洗并使用相同的种子初始化对象。 – itsme86

回答

5

使用像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)); 
+0

不错!我发誓我在我的小扩展库中有完全相同的代码。 – itsme86

3

而不是使用的O(N log n)的排序重新洗牌(别提产生Guid值的开销),你应该使用Random和标准为O(n)Fisher - Yatesshuffle。然后你可以在每次执行时给Random对象一样的种子。

相关问题