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 Select
und Where
um ~ 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. Select
und Where
jetzt 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 Select
und Where
den 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 Select
und 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 Select
Linie stabil bleibt (erwartet) und dass die Select + Where
Linie steigt (erwartet). Was mich jedoch verwundert, ist, warum es nicht mit dem Select
bei 50 oder früher übereinstimmt: Tatsächlich hatte ich früher als 50 erwartet, da ein zusätzlicher Enumerator für das Select
und 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 Where
und Select
Kombination 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
+ Select
verursacht keine zwei getrennten Iterationen über die Eingabesammlung. LINQ to Objects optimiert es in einer Iteration. Lesen Sie mehr auf meinem Blog-Beitrag
mc.Value
sind.