あなたはそのようなシャッフルがどのように機能するかを理解するのにかなり近づいています..あなたの2番目のケースでは
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 に基づいてソートされます。
GUIDとは何ですか?
これらは、16 進形式で表される 128 ビットの整数です。2^128 は非常に大きな数であるため、2 つの Guid を生成する可能性は非常にまれであり、ほとんど不可能です。Guid はある種のランダム性を示すため、順序もランダムになります。
順序を強制するために 2 つの 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());
}