У мене клас, як це:
public class MyClass
{
public int Value { get; set; }
public bool IsValid { get; set; }
}
Насправді це набагато більше, але це відтворює проблему (дивності).
Я хочу отримати суму Value, де дійсний екземпляр. Поки що я знайшов два рішення для цього.
Перший - це:
int result = myCollection.Where(mc => mc.IsValid).Select(mc => mc.Value).Sum();
Однак другий:
int result = myCollection.Select(mc => mc.IsValid ? mc.Value : 0).Sum();
Я хочу отримати найбільш ефективний метод. Я, по-перше, думав, що другий буде ефективнішим. Тоді теоретична частина мене почала йти: "Ну, один - O (n + m + m), другий - O (n + n). Перший повинен працювати краще, ніж більше інвалідів, а другий повинен працювати краще з меншою ». Я думав, що вони будуть виступати однаково. EDIT: І тоді @Martin вказував, що Де і Вибір поєднані, тому насправді це повинно бути O (m + n). Однак якщо подивитися нижче, здається, це не пов’язано.
Тому я поставив це на тест.
(Це 100+ рядків, тому я подумав, що краще опублікувати це як історію.)
Результати були ... цікаві.
З дотриманням 0% відхилення:
Ваги знаходяться в користь Selectі Where, приблизно ~ 30 балів.
How much do you want to be the disambiguation percentage?
0
Starting benchmarking.
Ties: 0
Where + Select: 65
Select: 36
З 2% відхиленням:
Це те саме, за винятком того, що для деяких вони були в межах 2%. Я б сказав, що це мінімальна помилка. Selectі Whereтепер маєте лише 20-кратне відрив.
How much do you want to be the disambiguation percentage?
2
Starting benchmarking.
Ties: 6
Where + Select: 58
Select: 37
З 5% -ним відхиленням:
Це я б сказав, що це моя максимальна помилка. Це робить його трохи краще для Select, але не набагато.
How much do you want to be the disambiguation percentage?
5
Starting benchmarking.
Ties: 17
Where + Select: 53
Select: 31
З дотриманням 10% відхилення:
Це вихід з моєї помилки, але мене все ще цікавить результат. Тому що це дає Selectі Whereдвадцять очок, які він мав на деякий час.
How much do you want to be the disambiguation percentage?
10
Starting benchmarking.
Ties: 36
Where + Select: 44
Select: 21
З дозволом на 25%:
Це шлях, шлях з мого краю помилки, але я все ще зацікавлений в результаті, тому що Selectі до Where сих пір (майже) тримати їх 20 очок. Здається, що це перевершує це на декількох кількох, і саме це дає йому перевагу.
How much do you want to be the disambiguation percentage?
25
Starting benchmarking.
Ties: 85
Where + Select: 16
Select: 0
Зараз я здогадуюсь, що 20-бальний відрив прийшов із середини, де вони обоє зобов'язані обійти одну й ту ж виставу. Я міг би спробувати ввійти, але це було б цілком завантажене інформацією. Графік був би кращим, я думаю.
Отже, це я і зробив.

Це показує, що Selectлінія тримається стійкою (очікуваною) і що Select + Whereлінія піднімається вгору (очікується). Однак, що спантеличує мене, чому він не зустрінеться з Selectна 50 або вище: насправді я очікував раніше , ніж 50, в якості додаткового переписувач мав бути створений для SelectіWhere . Я маю на увазі, це показує 20-кратну перевагу, але це не пояснює, чому. Це, мабуть, головний момент мого питання.
Чому він поводиться так? Чи варто їй довіряти? Якщо ні, чи слід використовувати інший чи цей?
Як в коментарях згадував @KingKong, ви також можете використовувати Sum перевантаження, яке лямбда. Тож два мої варіанти тепер змінені на це:
Перший:
int result = myCollection.Where(mc => mc.IsValid).Sum(mc => mc.Value);
Друге:
int result = myCollection.Sum(mc => mc.IsValid ? mc.Value : 0);
Я зроблю його трохи коротше, але:
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
Двадцятибальний відрив все ще існує, це означає, що це не має відношення до WhereтаSelect комбінації вказували @Marcin в коментарях.
Дякуємо, що прочитали мою стінку тексту! Крім того, якщо вам цікаво, ось модифікована версія, що записує CSV, який приймає Excel.
Where+ Selectне викликає двох відокремлених ітерацій над колекцією вхідних даних. LINQ to Objects оптимізує його в одну ітерацію. Детальніше читайте на моєму щоденнику


mc.Value.