2012-01-18 40 views
1

另一名單上遺漏值我有一個IEnumerable的,其中SaleReport的模型如下:灌漿基礎的INT

public int ID { get; set; } 
    public DateTime StartDate { get; set; } 
    public DateTime EndDate { get; set; } 
    public decimal Amount { get; set; } 
    public SalesReportProduct Product { get; set; } 
    public int ItemID { get; set; } 
    public int LanguageID { get; set; } 
    public int ProductID { get; set; } 

我填補這一IEnumerable的基於datetime值數據庫條目:

salesReports = _salesReport.GetAll(fromDate, toDate); 

然後,我有是所有可用的項目ID int類型的列表:

var ItemIDList = new List<int>(); 

我的問題是,我必須插入所有不屬於IEnumerable的ItemID的SalesReport,因此對於ItemIDList的每個值,我檢查IEnumerable中是否至少有一個對應的ItemID,如果不是,則必須附加一個新的SalesReport項目ID。

我該如何輕鬆做到這一點?

回答

1

您可以使用Range & Except函數來執行此操作。

var unusedIds = Enumerable.Range(1, _salesReport.select(sr => sr.ItemID).Max()) 
       .Except(_salesReport.select(sr => sr.ItemID)); 
ItemIDList.AddRange(unusedIds); 

我不知道該Except功能多麼昂貴的是,在猜測它做了Find_salesReport爲範圍內的每個項目。我會查找並回復你。

。 。 。當然我錯了Jon Skeets EudlinqExcept的實現只消耗每個序列一次,ILSpy向我展示了.Net源代碼中的類似優化。

NB:到Max()的調用來獲取整數的範圍將 - 當然 - 通過_salesReport重複一次,所以在這個總遍歷_salesReport兩次。

如果這是太貴了,你可以從_salesReport

var usedIds = _salesReport.select(sr => sr.ItemID).ToList(); 
var unusedIds = Enumerable.Range(1, usedIds.Max()).Except(usedIds); 
ItemIDList.AddRange(unusedIds); 

緩存的ID。 。 。實際上,你可以爲自己節省一個號碼。 我們在列表中查看是否是Max(),但是我們知道Max是在列表中,因爲我們從列表那裏得到它,因此我們不需要在數字範圍內包含Max去檢查。

var usedIds = _salesReport.select(sr => sr.ItemID).ToList(); 
var unusedIds = Enumerable.Range(1, usedIds.Max() - 1).Except(usedIds); 
ItemIDList.AddRange(unusedIds); 
0

作爲練習,我試着在儘可能最有效的方式來解決這個問題:

 var reports = _salesReports.OrderBy(x=>x.ItemId).Select(x=>x.ItemId); 
     var requiredReports = ItemIdList.OrderBy(x=>x); 

     int reportsCount = reports.Count(); 
     int requiredCount = requiredReports.Count(); 

     List<int> missingReports = new List<int>(); 

     int reportIndex = 0; 
     int requiredIndex = 0; 
     while (reportIndex < reportsCount && requiredIndex < requiredCount) 
     { 
      if (reports[reportIndex] == requiredReports[requiredIndex]) 
      { 
       reportIndex++; 
       requiredIndex++; 
       continue; 
      } 
      if (reports[reportIndex] < requiredReports[requiredIndex]) 
      { 
       reportIndex++; 
       continue; 
      } 
      if (reports[reportIndex] > requiredReports[requiredIndex]) 
      { 
       missingReports.Add(requiredReports[requiredIndex]); 
       requiredIndex++; 
       continue; 
      } 
     } 
     for (var i = requiredIndex; i < requiredCount; i++) 
     { 
      missingReports.Add(requiredReports[i]); 
     } 

顯然,對於代碼清晰,你應該使用Linq。這是爲了避免不得不多次迭代列表,但這樣做的代價對於清楚理解代碼的能力來說是值得的。