2010-11-11 30 views
1

我有一個項目的集合,其中每個項目都有一個「日期」字段(代碼如下)。如何處理LINQ中的源數據更改?

我想填補使用LINQ的集合中日期中的任何空白。特別是,我希望得到的序列包含原始序列中第一天和最後一天之間的所有天數。

除此之外,我的結果LINQ查詢應該能夠處理原始序列的任何修改。那就是我無法提前計算最小和最大日期。

所以我試了下面的代碼,但它試圖計算序列的最小值和最大值時失敗。我正在尋找一個「懶惰」的選擇。

感謝您的幫助 康斯坦丁


using System; 
using System.Collections.Generic; 
using System.Collections.ObjectModel; 
using System.Linq; 

namespace consapp 
{ 
    class C 
    { 
     public DateTime date; 
     public int? value; 
    } 

    static class Program 
    { 
     static IEnumerable<C> dates(DateTime d0, DateTime d1) 
     { 
      for (var d = d0; d <= d1; d = d.AddDays(1)) 
      { 
       yield return new C { date = d }; 
      } 
     } 

     static void Main(string[] args) 
     { 
      var xs = new ObservableCollection<C>(); 

      var q = from d in dates(xs.Min(y => y.date), xs.Max(y => y.date)) 
        join x in xs on d.date equals x.date into js 
        from j in js.DefaultIfEmpty() 
        orderby d.date 
        select new { date = d.date, value = j != null ? j.value : null }; 

      xs.Add(new C { date = DateTime.Parse("11/10/11") }); 
      xs.Add(new C { date = DateTime.Parse("02/02/11") }); 
      xs.Add(new C { date = DateTime.Parse("11/24/11") }); 
      xs.Add(new C { date = DateTime.Parse("09/09/11") }); 
      xs.Add(new C { date = DateTime.Parse("11/10/11") }); 

      foreach (var x in q) 
      { 
       Console.WriteLine(x.date.ToShortDateString()); 
      } 
     } 
    } 
} 
+0

你好konstantin,因爲Stackoverflow是一個社區編輯的QnA列表,你應該編輯你的問題標題。或者你對「需要linq幫助」這個問題期待什麼樣的答案?問候 – Zeemee 2010-11-11 16:08:41

+0

@穆爾穆特:謝謝,希望新的主題行更具體 – akonsu 2010-11-11 16:15:34

回答

1

我不是絕對肯定,但:

var q = from d in dates(xs.Min(y => y.date), xs.Max(y => y.date)) 

我相信「日期」方法將立即被調用,並且LINQ查詢的其餘部分(包括來自dates()本身的迭代器)將圍繞該方法的結果構建。所以你將不得不預先在你感興趣的數據中填充xs

這是因爲LINQ本質上是通過將可枚舉枚舉包裝在其他枚舉類型中工作的。爲了做到這一點,它必須從一個枚舉開始。爲了做到這一點,它必須調用order()方法,其中要求立即提供其參數,以便它可以接收將要包裝在其他枚舉中的可枚舉對象。因此,當達到該行代碼時,將調用xs.Minxs.Max方法,但實際上不會處理查詢中的任何其他內容。

解決方法是讓您的dates()方法實際上收到ObservableCollection並自行呼叫Min/Max。因爲這將發生在生成的迭代器中,所以這些調用的執行將按照您的預期推遲。

+0

將整個集合傳遞給dates()作品。謝謝。 – akonsu 2010-11-11 16:18:56

0

標準LINQ實現了基於IEnumerable<T>不能處理作爲ObservableCollection改變這樣的數據源。您的示例失敗的原因是它會嘗試評估數據源(並在定義查詢時調用dates函數和MinMax運算符)(但該數據源在該點上不包含任何數據)。

  • 一種選擇是使用替代的LINQ實現與ObservableCollection工作,並且可以自動更新結果的來源發生變化時。據我所知Bindable LINQ項目應該能夠做到這一點。

  • 另一個(更簡單的)選項是當您知道數據源已更改時,將查詢轉變爲方法並重復調用方法(以更新結果)。你不得不做出ObservableCollection私有字段和方法只會運行使用當前存儲在集合中的數據:

    private ObservableCollection source; 
    void UpdateResults() { 
        var q = /* The query goes here */ 
        // Do something with the result of the query 
    } 
    
+0

感謝您的參考。我只是試着在那個頁面中的示例代碼,他們說沒有在屏幕上顯示任何東西,它似乎工作。我正在使用.net 4.0。看來他們現在在LINQ中有這種能力,不是嗎? – akonsu 2010-11-11 16:11:52

相關問題