你非常接近理解这种洗牌是如何工作的。在你的第二种情况下
pupils.OrderBy(x => x.Age);
被Comparer<int>.Default
使用(这些人是按他们的Age
,简单的)。
在您的第一种情况下,Comparer<Guid>.Default
使用。
现在它是如何工作的?.
每次你这样做Guid.NewGuid()
(大概)都会产生不同的/原始的/非重复Guid
的。现在当你做
var randomNumbers = Enumerable.Range(0, 100).OrderBy(x => Guid.NewGuid());
这些数字根据生成的 Guid 进行排序。
现在什么是指南?
它们是以十六进制形式表示的 128 位整数。由于 2^128 是如此之大,因此生成两个 Guid 的机会非常罕见/几乎不可能。由于 Guid 表现出某种随机性,因此排序也是随机的。
如何比较两个 Guid 以强制执行排序?
您可以根据一个简单的实验来确认它。做:
var guids = Enumerable.Range(0, 10).Select((x, i) =>
{
Guid guid = Guid.NewGuid();
return new { Guid = guid, NumberRepresentation = new BigInteger(guid.ToByteArray()), OriginalIndex = i };
}).ToArray();
var guidsOrderedByTheirNumberRepresentation = guids.OrderBy(x => x.NumberRepresentation).ToArray();
var guidsOrderedAsString = guids.OrderBy(x => x.Guid.ToString()).ToArray();
var randomNumbers = Enumerable.Range(0, 10).OrderBy(x => guids[x].Guid).ToArray();
//print randomNumbers.SequenceEqual(guidsOrderedByTheirNumberRepresentation.Select(x => x.OriginalIndex)) => false
//print randomNumbers.SequenceEqual(guidsOrderedAsString.Select(x => x.OriginalIndex)) => true
所以Comparer<Guid>.Default
是基于guid的字符串表示。
在旁边:
您应该使用Fisher-Yates改组来提高速度。或许
public static IEnumerable<T> Shuffle<T>(this IList<T> lst)
{
Random rnd = new Random();
for (int i = lst.Count - 1; i >= 0; i--)
{
int j = rnd.Next(i + 1);
yield return lst[j];
lst[j] = lst[i];
}
}
或者为了简洁起见,可能只是(这仍然比 Guid 方法更快)
public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> lst)
{
Random rnd = new Random();
return lst.OrderBy(x => rnd.Next());
}