У меня есть класс, как это:
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). Первый должен работать лучше с большим количеством инвалидов, а второй должен работать лучше. менее". Я думал, что они будут работать одинаково. РЕДАКТИРОВАТЬ: И затем @Martin указал, что Where и Select были объединены, так что на самом деле это должно быть O (m + n). Однако, если вы посмотрите ниже, кажется, что это не связано.
Поэтому я проверил это.
(Это более 100 строк, поэтому я подумал, что было бы лучше опубликовать его в виде Gist.)
Результаты были ... интересными.
С 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ней.