2013-05-16 71 views
0

我想使用Linq與數據表的價值得到以下集團使用LINQ

DataTable的內容

periodstart periodend value 
2013-01-01 2013-02-01 10 
2013-02-02 2013-03-01 10 
2013-03-02 2013-04-01 15 
2013-04-02 2013-05-01 20 
2013-05-02 2013-06-01 10 
2013-06-02 2013-07-02 20 

結果

2013-01-01 2013-03-01 10 
2013-03-02 2013-04-01 15 
2013-04-02 2013-05-01 20 
2013-05-02 2013-06-01 10 
2013-06-02 2013-07-02 20 

基本上我想組時間段的數據表值,但如果在兩者之間存在不同的分組,則也允許重複相同的值。

我想通過使用週期的最小值和最大值值值與組去,但會給我像

2013-01-01 2013-06-01 10 
2013-03-02 2013-04-01 15 
2013-04-02 2013-07-02 20 

這是不正確。

如何解決此問題?

+0

是你的月經總是連續和非重疊?他們總是訂購嗎? (所以我們可以只用「具有相同值的連續期間」進行分組?) –

+0

@JonSkeet是週期是連續的且不重疊的! – mko

+0

已經訂購了?大概你可以把它作爲第一步分開...... –

回答

0

(添加一個單獨的答案,因爲我現在刪除的是錯誤的。)

這聽起來像你只需要遍歷所有行,保持一組下去,直到值部分的更改,然後服用開始第一個元素的結尾和最後一個元素的結尾。所以,你可以做這樣的事情作爲一個擴展的方法:

public static IEnumerable<IEnumerable<T>> GroupByContiguous<T, TKey> 
    (this IEnumerable<T> source, Func<T, TKey> groupSelector) 
{ 
    List<T> currentGroup = new List<T>(); 
    T groupKey = default(T); 
    // This could be passed in as a parameter 
    EqualityComparer<T> comparer = EqualityComparer<T>.Default; 
    using (var iterator = source.GetEnumerator()) 
    { 
     if (!iterator.MoveNext()) 
     { 
      yield break; 
     } 
     groupKey = groupSelector(iterator.Current); 
     currentGroup.Add(iterator.Current); 
     while (iterator.MoveNext()) 
     { 
      var item = iterator.Current; 
      var key = groupSelector(item); 
      if (!comparer.Equals(groupKey, key)) 
      { 
       yield return currentGroup.Select(x => x); 
       currentGroup = new List<T>(); 
       groupKey = key; 
      } 
      currentGroup.Add(item); 
     }    
    } 
    // Trailing group 
    yield return currentGroup.Select(x => x); 
} 

然後用這個爲:

var query = table.AsEnumerable() 
       .GroupByContiguous(row => row.Field<int>("value")) 
       .Select(g => new { 
        Value = g.Key, 
        EarliestStart = g.First().Field<DateTime>("periodstart"), 
        LatestEnd = g.Last().Field<DateTime>("periodend") 
       });