Mam taką klasę:
public class MyClass
{
public int Value { get; set; }
public bool IsValid { get; set; }
}
W rzeczywistości jest znacznie większy, ale to odtwarza problem (dziwność).
Chcę uzyskać sumę Value, gdzie instancja jest prawidłowa. Jak dotąd znalazłem dwa rozwiązania tego problemu.
Pierwsza z nich to:
int result = myCollection.Where(mc => mc.IsValid).Select(mc => mc.Value).Sum();
Drugi to jednak:
int result = myCollection.Select(mc => mc.IsValid ? mc.Value : 0).Sum();
Chcę uzyskać najbardziej wydajną metodę. Na początku myślałem, że ten drugi będzie bardziej wydajny. Wtedy część teoretyczna mnie zaczęła mówić "No cóż, jedna to O (n + m + m), druga to O (n + n). Pierwsza powinna działać lepiej z większą liczbą inwalidów, a druga powinna działać lepiej mniej ”. Pomyślałem, że będą działać równie dobrze. EDYCJA: A potem @Martin wskazał, że Gdzie i Wybierz zostały połączone, więc powinno to być O (m + n). Jeśli jednak spojrzysz poniżej, wygląda na to, że nie ma to związku.
Więc wystawiłem to na próbę.
(To ponad 100 wierszy, więc pomyślałem, że lepiej będzie opublikować to jako streszczenie)
. Wyniki były ... interesujące.
Z 0% tolerancją krawata:
Skale są na korzyść Selecti Where, o około ~ 30 punktów.
How much do you want to be the disambiguation percentage?
0
Starting benchmarking.
Ties: 0
Where + Select: 65
Select: 36
Z 2% tolerancją krawata:
To jest to samo, z wyjątkiem tego, że dla niektórych były w granicach 2%. Powiedziałbym, że to minimalny margines błędu. Selecta Whereteraz mają tylko ~ 20 punktów przewagi.
How much do you want to be the disambiguation percentage?
2
Starting benchmarking.
Ties: 6
Where + Select: 58
Select: 37
Z 5% tolerancją krawata:
To właśnie powiedziałbym, że jest to mój maksymalny margines błędu. To sprawia, że jest trochę lepiej Select, ale niewiele.
How much do you want to be the disambiguation percentage?
5
Starting benchmarking.
Ties: 17
Where + Select: 53
Select: 31
Z 10% tolerancją krawata:
To jest poza moim marginesem błędu, ale nadal jestem zainteresowany wynikiem. Bo to daje Selecti Wherepunkt dwadzieścia prowadzić to miałem na chwilę teraz.
How much do you want to be the disambiguation percentage?
10
Starting benchmarking.
Ties: 36
Where + Select: 44
Select: 21
Z 25% tolerancją krawata:
To jest sposób, aby wyjść poza mój margines błędu, ale nadal jestem zainteresowany wynikiem, ponieważ Selecti Where nadal (prawie) utrzymują swoją 20-punktową przewagę. Wygląda na to, że deklasuje go w kilku wyraźnych i to właśnie daje mu przewagę.
How much do you want to be the disambiguation percentage?
25
Starting benchmarking.
Ties: 85
Where + Select: 16
Select: 0
Zgaduję, że 20-punktowa przewaga nadeszła ze środka, gdzie obaj będą musieli obejść ten sam występ. Mógłbym spróbować to zarejestrować, ale byłoby to całe mnóstwo informacji do zebrania. Wykres byłby lepszy, jak sądzę.
Więc to właśnie zrobiłem.

Pokazuje, że Selectlinia pozostaje stabilna (oczekiwana) i że Select + Wherelinia wznosi się (oczekiwana). Zastanawiające mnie jednak, dlaczego nie spotyka się z Select50 lub wcześniej: tak naprawdę spodziewałem się wcześniej niż 50, ponieważ trzeba było stworzyć dodatkowy wyliczający dla Selecti Where. To znaczy, to pokazuje 20-punktową przewagę, ale nie wyjaśnia dlaczego. To chyba jest główny punkt mojego pytania.
Dlaczego tak się zachowuje? Powinienem mu ufać? Jeśli nie, powinienem użyć drugiego czy tego?
Jak @KingKong wspomniał w komentarzach, możesz również użyć Sumprzeciążenia, które pobiera lambdę. Więc moje dwie opcje są teraz zmienione na:
Pierwszy:
int result = myCollection.Where(mc => mc.IsValid).Sum(mc => mc.Value);
Druga:
int result = myCollection.Sum(mc => mc.IsValid ? mc.Value : 0);
Mam zamiar to trochę skrócić, ale:
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
Dwudziestopunktowa przewaga wciąż istnieje, co oznacza, że nie ma nic wspólnego z kombinacją Wherei Selectwskazaną przez @Marcin w komentarzach.
Dziękuję za przeczytanie mojej ściany tekstu! Ponadto, jeśli jesteś zainteresowany, oto zmodyfikowana wersja, która rejestruje plik CSV pobierany przez program Excel.
Where+ Selectnie powoduje dwóch oddzielnych iteracji po kolekcji danych wejściowych. LINQ to Objects optymalizują go w jednej iteracji. Przeczytaj więcej na moim blogu


mc.Valueniej.