2011-09-11 3 views
1

지정된 클래스 :그룹화하지 않고 단일 linq 문에서 둘 이상의 값을 Sum() 할 수 있습니까?

public class FooAmounts 
int Id 
decimal Month1 
decimal Month2 
... 
decimal Month12 
decimal Year2 
decimal Year3 
decimal Future 

나는 매달의 합계를 가지고 하나의 새로운 FooAmounts를 만들 싶습니다

5 개 항목 (! 충분히 재미있게 아이디의 1-5)와 IEnumerable<FooAmounts>/년이 Id == 1 + Id == 2 인 경우에만 예.

var footle = (from f in foolist 
where f.Id == 1 || f.Id == 2 
select new FooAmounts{ 
Month1 = Sum(month 1s), 
Month2 = Sum(month 2s), 
etc etc. 
Future = Sum(futures) 
).FirstOrDefault(); 

나는 다시 생성이 T-SQL에 노력하고 있습니다 :

select SUM(Month1) as Month1, SUM(Month2) as Month2, SUM(Month3) as Month3 from FooAmount where Id=1 or Id=2" 

가 나는 group by f.Id into grp 절을 사용하여 유사한 acheive 수 있지만이 두 가지 항목으로 나를 잎 그러므로 내가 첫째를 사용할 수 없습니다/FoD, 나는 수동으로 그들을 합쳐야 할 것임을 의미한다. .. 나는 어떤 곳에서 트릭을 놓치고있는 것처럼 보인다?

참고 : FirstOrDefault()는 오직 하나의 개체를 포함하는 하나의 개체가 아니라 하나의 개체를 반환합니다. 나는 어쨌든 항상 하나의 항목 만 리턴해야한다고 생각한다. 아마도 계산에 들어가는 항목의 수에 관계없이 Sum()의 결과는 하나 뿐이다.

답변

1

값이 하나가 많든 많든 상관없이 합계의 첫 번째 결과를 얻는 것은 의미가 없습니다.

I 10 사람이 있다면, 나는 첫 번째의 나이를 찾을 수 있습니다, 또는 나는 세 그들 모두의 합을 찾을 수 있습니다 -하지만 난 시대의 합계를 찾을 수 없습니다 . 그래서 당신은 할 수있다 :

var matches = fooList.Where(f => f.Id == 1 || f.Id == 2); 

var sum = new FooAmounts { Month1 = matches.Sum(f => f.Month1), 
          Month2 = matches.Sum(f => f>Month2), 
          ... }; 

이제 쿼리가 여러 번 실행될 것이다. 대신 쿼리를 구체화 할 수 있고, 그 위에 합산을 수행

// Materialize the result so we only filter once 
var matches = fooList.Where(f => f.Id == 1 || f.Id == 2).ToList(); 

var sum = new FooAmounts { Month1 = matches.Sum(f => f.Month1), 
          Month2 = matches.Sum(f => f>Month2), 
          ... }; 

을 또는 대안 당신은 집계 사용할 수 있습니다

var sum = fooList.Where(f => f.Id == 1 || f.Id == 2) 
        .Aggregate(new FooAmounts(), // Seed 
          (sum, item) => new FooAmounts { 
           Month1 = sum.Month1 + item.Month1, 
           Month2 = sum.Month2 + item.Month2, 
           ... 
          }); 

이 한 번만 순서를 반복합니다, 그리고 큰를 만들 수 없습니다 버퍼를 메모리에 저장하지만, 반복 될 때 FooAmounts 인스턴스가 많이 생성됩니다. 나에게 약간 불쾌한 느낌의

var sum = fooList.Where(f => f.Id == 1 || f.Id == 2) 
        .Aggregate(new FooAmounts(), // Seed 
          (sum, item) => { 
           sum.Month1 += item.Month1; 
           sum.Month2 += item.Month2; 
           ... 
           return sum; 
          }); 

을하지만 나쁜 방법으로하지 정말이 부작용을 수행

당신 물론, 장소에 축적를 수정할 수 있습니다 어쨌든 호출 내에서 초기화되는 객체를 변경하는 것뿐입니다.

+0

Apols, 아마도 심하게 말로 표현됩니다. 간단히 말하면 합계를 포함하는 끝에 하나의 객체를 가져오고, 객체 목록 (이미 가지고있는 것) 또는 매월 Sum (s => s.property)을해야합니다 ... Year 나는 원했다. – BlueChippy

+0

@BlueChippy : 내 게시물을 더 많은 옵션으로 편집했습니다. 나는 그 옵션을 넘어서는 단순하고 우아한 아무것도 없다고 생각합니다. –

+0

감사합니다 Jon - 나는이 t-sql와 동등한 "Select SUM (Month1) Month1, SUM (Month2) Month2, SUM (Month3) Month3 FooAmount에서 Id = 1 또는 Id = 2"로 다시 만들려고했습니다. :) – BlueChippy

관련 문제