Führt orderby () in LINQ die Vergleichsfunktion nur einmal aus oder führt sie bei Bedarf aus?

9

Ich habe eine Methode gefunden, um ein Array im Internet zu mischen.

%Vor%

Ich bin jedoch ein wenig besorgt über die Richtigkeit dieser Methode. Wenn OrderBy x => rand.Next() mehrmals für dasselbe Objekt ausführt, können die Ergebnisse Konflikte verursachen und zu seltsamen Dingen (möglicherweise Ausnahmen) führen.

Ich habe es versucht und alles ist in Ordnung, aber ich möchte immer noch wissen, ob das absolut sicher ist und immer wie erwartet funktioniert, und ich kann die Antwort von Google nicht finden.

Könnte mir jemand Erklärungen geben?

Vielen Dank im Voraus.

    
LLS 18.10.2010, 09:47
quelle

3 Antworten

3

Ihr Ansatz sollte funktionieren, aber es ist langsam.

Es funktioniert, weil OrderBy zuerst die Schlüssel für jedes Element mit der Schlüsselauswahl berechnet und dann die Schlüssel sortiert. Der Schlüsselwähler wird also nur einmal pro Element aufgerufen.

In .NET Reflector sehen Sie die Methode ComputeKeys in der Klasse EnumerableSorter .

%Vor%
  

ob dies absolut sicher ist und immer wie erwartet funktioniert

Es ist undokumentiert, also könnte es sich in der Theorie in Zukunft ändern.

Zum zufälligen Mischen können Sie den Fisher-Yates Shuffle verwenden. Dies ist auch effizienter - es werden nur O (n) Zeit und Mischen anstelle von O (n log (n)) Zeit und O (n) Extra-Speicher verwendet.

Verwandte Frage

Mark Byers 18.10.2010, 09:55
quelle
1

Ich gehe davon aus, dass Sie über LINQ-to-Objects sprechen. In diesem Fall wird der für den Vergleich verwendete Schlüssel nur einmal pro Element generiert. (Beachten Sie, dass dies nur ein Detail der aktuellen Implementierung ist und sich ändern könnte, obwohl dies sehr unwahrscheinlich ist, da eine solche Änderung die von Ihnen erwähnten Fehler einführt.)

Um Ihre allgemeinere Frage zu beantworten: Ihr Ansatz sollte funktionieren, aber es gibt bessere Möglichkeiten, dies zu tun. Die Verwendung von OrderBy wird normalerweise O (n log n) Leistung sein, während ein Fisher-Yates-Durstenfeld shuffle wird O (n) sein.

(Es gibt eine Beispiel Shuffle Erweiterung für IEnumerable<T> hier oder eine im-Platz entspricht für IList<T> hier , wenn Sie bevorzugen.)

    
LukeH 18.10.2010 09:55
quelle
0

Die Verwendung eines shufflebag wird definitiv funktionieren.

Was Ihre Methode anbetrifft, denke ich, dass es nicht völlig zufällig ist, da die Reihenfolge der gleichen Elemente beibehalten wird. Wenn Sie also ein zufälliges Array [5 6 7 2 6] haben, werden die Elemente an den beiden Sechsen immer in der gleichen Reihenfolge sein.

Ich müsste einen Frequenztest durchführen, um sicher zu sein.

    
Carra 18.10.2010 09:54
quelle

Tags und Links