Ich habe eine Klasse wie diese:
public class MyClass
{
public int Value { get; set; }
public bool IsValid { get; set; }
}
Tatsächlich ist es viel größer, aber dies schafft das Problem (Verrücktheit) neu.
Ich möchte die Summe von erhalten Value, wo die Instanz gültig ist. Bisher habe ich zwei Lösungen dafür gefunden.
Der erste ist dieser:
int result = myCollection.Where(mc => mc.IsValid).Select(mc => mc.Value).Sum();
Der zweite ist jedoch folgender:
int result = myCollection.Select(mc => mc.IsValid ? mc.Value : 0).Sum();
Ich möchte die effizienteste Methode erhalten. Zuerst dachte ich, dass der zweite effizienter sein würde. Dann fing der theoretische Teil von mir an zu sagen: "Nun, einer ist O (n + m + m), der andere ist O (n + n). Der erste sollte mit mehr Invaliden besser abschneiden, während der zweite besser abschneiden sollte mit weniger". Ich dachte, dass sie gleich gut abschneiden würden. EDIT: Und dann wies @Martin darauf hin, dass Where und Select kombiniert wurden, also sollte es eigentlich O (m + n) sein. Wenn Sie jedoch nach unten schauen, scheint dies nicht miteinander verbunden zu sein.
Also habe ich es auf die Probe gestellt.
(Es sind mehr als 100 Zeilen, daher dachte ich, es wäre besser, es als Kern zu veröffentlichen.)
Die Ergebnisse waren ... interessant.
Mit 0% Bindungstoleranz:
Die Skalen sprechen für Selectund Whereum ~ 30 Punkte.
How much do you want to be the disambiguation percentage?
0
Starting benchmarking.
Ties: 0
Where + Select: 65
Select: 36
Mit 2% Bindungstoleranz:
Es ist das gleiche, außer dass sie für einige innerhalb von 2% lagen. Ich würde sagen, das ist eine minimale Fehlerquote. Selectund Wherejetzt haben nur noch ~ 20 Punkte Vorsprung.
How much do you want to be the disambiguation percentage?
2
Starting benchmarking.
Ties: 6
Where + Select: 58
Select: 37
Mit 5% Bindungstoleranz:
Dies würde ich als meine maximale Fehlerquote bezeichnen. Es macht es ein bisschen besser für die Select, aber nicht viel.
How much do you want to be the disambiguation percentage?
5
Starting benchmarking.
Ties: 17
Where + Select: 53
Select: 31
Mit 10% Bindungstoleranz:
Dies ist ein Ausweg aus meiner Fehlerquote, aber ich bin immer noch am Ergebnis interessiert. Weil es den Selectund Whereden 20-Punkte-Vorsprung gibt, den es schon eine Weile hat.
How much do you want to be the disambiguation percentage?
10
Starting benchmarking.
Ties: 36
Where + Select: 44
Select: 21
Mit 25% Bindungstoleranz:
Dies ist übrigens Weg aus meiner Fehlermarge, aber ich bin immer noch im Ergebnis interessiert, weil das Selectund Where noch (fast) ihren 20 - Punkte - Vorsprung halten. Es scheint, als würde es in einigen wenigen Punkten übertroffen, und genau das gibt ihm die Führung.
How much do you want to be the disambiguation percentage?
25
Starting benchmarking.
Ties: 85
Where + Select: 16
Select: 0
Nun, ich nehme an, dass der 20 - Punkte - Vorsprung aus der Mitte kam, wo sie beide gebunden sind , zu erhalten , um die gleiche Leistung. Ich könnte versuchen, es zu protokollieren, aber es wäre eine ganze Menge Informationen, die ich aufnehmen müsste. Ein Diagramm wäre besser, denke ich.
Das habe ich also getan.

Es zeigt, dass die SelectLinie stabil bleibt (erwartet) und dass die Select + WhereLinie steigt (erwartet). Was mich jedoch verwundert, ist, warum es nicht mit dem Selectbei 50 oder früher übereinstimmt: Tatsächlich hatte ich früher als 50 erwartet, da ein zusätzlicher Enumerator für das Selectund erstellt werden musste Where. Ich meine, das zeigt den 20-Punkte-Vorsprung, aber es erklärt nicht warum. Dies ist wohl der Hauptpunkt meiner Frage.
Warum verhält es sich so? Soll ich ihm vertrauen? Wenn nicht, sollte ich den anderen oder diesen verwenden?
Wie @KingKong in den Kommentaren erwähnt, können Sie auch die SumÜberlastung verwenden, die ein Lambda benötigt. Meine beiden Optionen werden nun dahingehend geändert:
Zuerst:
int result = myCollection.Where(mc => mc.IsValid).Sum(mc => mc.Value);
Zweite:
int result = myCollection.Sum(mc => mc.IsValid ? mc.Value : 0);
Ich werde es etwas kürzer machen, aber:
How much do you want to be the disambiguation percentage?
0
Starting benchmarking.
Ties: 0
Where: 60
Sum: 41
How much do you want to be the disambiguation percentage?
2
Starting benchmarking.
Ties: 8
Where: 55
Sum: 38
How much do you want to be the disambiguation percentage?
5
Starting benchmarking.
Ties: 21
Where: 49
Sum: 31
How much do you want to be the disambiguation percentage?
10
Starting benchmarking.
Ties: 39
Where: 41
Sum: 21
How much do you want to be the disambiguation percentage?
25
Starting benchmarking.
Ties: 85
Where: 16
Sum: 0
Der zwanzig Punkte Vorsprung ist immer noch da, was bedeutet , es nicht mit dem zu tun hat Whereund SelectKombination von @Marcin in den Kommentaren darauf hingewiesen.
Vielen Dank für das Lesen meiner Textwand! Wenn Sie interessiert sind, finden Sie hier die geänderte Version, die die von Excel aufgenommene CSV protokolliert.
Where+ Selectverursacht keine zwei getrennten Iterationen über die Eingabesammlung. LINQ to Objects optimiert es in einer Iteration. Lesen Sie mehr auf meinem Blog-Beitrag


mc.Valuesind.