Ho una lezione, in questo modo:
public class MyClass
{
public int Value { get; set; }
public bool IsValid { get; set; }
}
In realtà è molto più grande, ma questo ricrea il problema (stranezza).
Voglio ottenere la somma di Value, dove l'istanza è valida. Finora ho trovato due soluzioni a questo.
Il primo è questo:
int result = myCollection.Where(mc => mc.IsValid).Select(mc => mc.Value).Sum();
Il secondo, tuttavia, è questo:
int result = myCollection.Select(mc => mc.IsValid ? mc.Value : 0).Sum();
Voglio ottenere il metodo più efficiente. Inizialmente pensavo che il secondo sarebbe stato più efficiente. Quindi la parte teorica di me ha iniziato ad andare "Bene, uno è O (n + m + m), l'altro è O (n + n). Il primo dovrebbe funzionare meglio con più invalidi, mentre il secondo dovrebbe funzionare meglio con meno". Ho pensato che si sarebbero comportati allo stesso modo. EDIT: E poi @Martin ha sottolineato che il Where e il Select sono stati combinati, quindi in realtà dovrebbe essere O (m + n). Tuttavia, se guardi sotto, sembra che questo non sia correlato.
Quindi l'ho messo alla prova.
(Sono più di 100 righe, quindi ho pensato che fosse meglio pubblicarlo come Gist.)
I risultati sono stati ... interessanti.
Con tolleranza allo 0%:
Le scale sono a favore di Selecte Where, di circa ~ 30 punti.
How much do you want to be the disambiguation percentage?
0
Starting benchmarking.
Ties: 0
Where + Select: 65
Select: 36
Con una tolleranza del 2%:
È lo stesso, tranne che per alcuni erano entro il 2%. Direi che è un margine minimo di errore. Selecte Whereora hanno solo un vantaggio di ~ 20 punti.
How much do you want to be the disambiguation percentage?
2
Starting benchmarking.
Ties: 6
Where + Select: 58
Select: 37
Con una tolleranza del 5%:
Questo è ciò che direi essere il mio massimo margine di errore. Lo rende un po 'meglio per il Select, ma non molto.
How much do you want to be the disambiguation percentage?
5
Starting benchmarking.
Ties: 17
Where + Select: 53
Select: 31
Con una tolleranza del 10%:
Questo è fuori dal mio margine di errore, ma sono ancora interessato al risultato. Perché dà il vantaggio di Selecte Whereil venti punti che ha avuto per un po 'di tempo.
How much do you want to be the disambiguation percentage?
10
Starting benchmarking.
Ties: 36
Where + Select: 44
Select: 21
Con una tolleranza del 25%:
Questo è un modo, molto al di fuori del mio margine di errore, ma sono ancora interessato al risultato, perché Selecte Where ancora (quasi) mantengono il vantaggio di 20 punti. Sembra che lo stia surclassando in pochi e questo è ciò che gli dà il vantaggio.
How much do you want to be the disambiguation percentage?
25
Starting benchmarking.
Ties: 85
Where + Select: 16
Select: 0
Ora, immagino che il vantaggio di 20 punti sia arrivato dal centro, dove entrambi sono tenuti a aggirare la stessa prestazione. Potrei provare a registrarlo, ma sarebbe un sacco di informazioni da prendere. Un grafico sarebbe meglio, immagino.
Quindi è quello che ho fatto.

Mostra che la Selectlinea rimane stabile (prevista) e che la Select + Wherelinea sale (prevista). Tuttavia, ciò che mi confonde è il motivo per cui non si incontra con il Select50 o precedente: in effetti mi aspettavo prima del 50, poiché è stato creato un enumeratore extra per Selecte Where. Voglio dire, questo mostra il vantaggio di 20 punti, ma non spiega il perché. Questo, immagino, è il punto principale della mia domanda.
Perché si comporta così? Dovrei fidarmi? In caso contrario, dovrei usare l'altro o questo?
Come menzionato da @KingKong nei commenti, puoi anche usare Sumil sovraccarico che prende un lambda. Quindi le mie due opzioni sono ora cambiate in questo:
Primo:
int result = myCollection.Where(mc => mc.IsValid).Sum(mc => mc.Value);
Secondo:
int result = myCollection.Sum(mc => mc.IsValid ? mc.Value : 0);
Lo renderò un po 'più breve, ma:
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
Il vantaggio di venti punti è ancora lì, il che significa che non ha a che fare con la combinazione Wheree Selectsottolineata da @Marcin nei commenti.
Grazie per aver letto attraverso il mio muro di testo! Inoltre, se sei interessato, ecco la versione modificata che registra il CSV utilizzato da Excel.
Where+ Selectnon causa due iterazioni separate sulla raccolta di input. LINQ to Objects lo ottimizza in un'unica iterazione. Maggiori informazioni sul mio post


mc.Value.