2013-01-17 2 views
0

나는 Created 필드 (날짜)를 가진 IEnumerable<T>입니다.
날짜 당 T이 여러 개있을 수 있으며 주어진 날짜에 T이없는 경우가 있습니다.누락 된 키가 포함 된 그룹 만들기

현재 이들을 날짜순으로 그룹화하여 하나의 숫자가 모두 T이고 그 아래에 T이있는 모든 날짜를 제공합니다.

내가 원하는 것은 주어진 날짜에 T이 있는지 여부에 관계없이 범위 내에서 모든 날짜를 얻을 수있는 쿼리의 일부로 사용할 수있는 것입니다.

현재 코드 : 여기

var adjustments = DAL.GetAdjustmentsInDateRange(Start, End); 

from adjustment in adjustments 
group adjustment by adjustment.Created.Date into adjustmentsByDay 
orderby adjustmentsByDay.Key descending 
select .... 

, adjustmentsByDayStartEnd 사이의 모든 날짜가 없습니다. 내가 원하는 것은 그것들을 포함하고 요소가없는 것이다.

어떻게하면됩니까?

답변

1

을 내가 조립 한에 가지 누락 삽입하는 확장 메서드를 LINQ는 - 투 - 객체 범용 순서 :

class EmptyGrouping<K, E> : IGrouping<K, E> { 
    public K Key { get; set; } 

    public IEnumerator<E> GetEnumerator() { 
     return Enumerable.Empty<E>().GetEnumerator(); 
    } 

    IEnumerator IEnumerable.GetEnumerator() { 
     return this.GetEnumerator(); 
    } 
} 
,369 :

public static IEnumerable<T> InsertMissing<T, U>(this IEnumerable<T> source, 
    Func<T, U> key, Func<U, U> increment, Func<U, T> create) 
{ 
    bool first = true; 
    U last = default(U); 

    foreach (var ig in source) 
    { 
     U current = key(ig); 

     if (first) 
     { 
      first = false; 
      last = current; 
      yield return ig; 
      continue; 
     } 

     while (!(last = increment(last)).Equals(current)) 
     { 
      yield return create(last); 
     } 

     yield return ig; 
    } 
} 

는 또한 IGrouping의 사용자 지정 구현을해야합니다

그럼 당신은이 호출을 따르 orderby 후 쿼리를 종료해야합니다, 다음 select 이후에 넣어 :

var allGroups = query.InsertMissing(
    // Key selector 
    g => g.Key, 
    // Get next desired key from current key 
    d => d.AddDays(-1), 
    // Create item for missing key 
    d => new EmptyGrouping<DateTime,YourAdjustmentType>{ Key = d }); 

열쇠를 주문하지 않을 경우이 훙 분하다거나 경우 그 중 하나가 올바른 위치에 있지 않습니다 (예 : 귀하의 경우에는 자정에 없습니다).

이것은 키 목록을 생성하기 위해 최소/최대 값을 결정하기 위해 원본 소스에서 여러 쿼리를 수행 할 필요가 없다는 이점이 있습니다. 그런 다음 데이터를 조인하고 가져 오기위한 추가 쿼리가 생성됩니다.

+0

좋습니다! 쿼리 확장 프로그램을 좋아해야합니다. –

2

당신과 같이 그룹화하기 전에 모든 날짜의 목록이 조정에 참여 왼쪽 수 :

var adjustments = DAL.GetAdjustmentsInDateRange(Start, End); 
// Get all unique dates in time span 
IEnumerable<DateTime> dates = GetAllDates(Start, End); 

var query = (from date in dates 
       join adjustment in adjustments 
        on date.Date equals adjustment.Created.Date into a 
       from adjustment in a.DefaultIfEmpty() 
       select new {date.Date, adjustment} 
       ).GroupBy(i=>i.Date).OrderBy(g=>g.Key); 
+0

'조정'이 'null'(나는 그 라인을 남겨두고 아래에 있음)이기 때문에 라인별로 그룹에 오류가 발생합니다. –

+0

구문 오류가 있으면 죄송합니다. Linq 101 왼쪽 된 외부 조인은 마지막 예제입니다. http://code.msdn.microsoft.com/101-LINQ-Samples-3fb9811b –

+0

이제 내 대답은 업데이트되었지만 그룹 및 순서는 메서드에 있습니다. 구문 및 쿼리 구문이 아닙니다. 이 솔루션은 저에게 효과적입니다. 처음에'Start'와'End'의 모든 날짜 목록을 만들 수 있다고 가정하면 –

관련 문제