다음과 같은 수업이 있습니다.
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
20 점의 리드를주기 때문입니다.
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 또는 그 이전 버전 과 만나지 않는 이유 입니다. 실제로 Select
and에 대해 추가 열거자를 만들어야했기 때문에 실제로 50보다 일찍 기대했습니다 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
20 점 리드는 여전히 있으며 이는 주석에서 @Marcin이 지적한 Where
및 Select
조합 과 관련이 없음을 의미합니다 .
내 성벽을 읽어 주셔서 감사합니다! 당신이 관심이 있다면 또한, 여기에 엑셀에 소요되는 CSV를 기록 수정 된 버전.
Where
+ Select
는 입력 콜렉션에 대해 두 개의 분리 된 반복을 일으키지 않습니다. LINQ to Objects는 한 번의 반복으로 최적화합니다. 내에서 자세히보기 블로그 게시물
mc.Value
.