2010-05-29 74 views
2

我無法將這一點邏輯轉換成Linq語句,這讓我發瘋。我有一個項目列表有一個類別和一個createdondate字段。我想按類別進行分組,並只返回具有其類別最大日期的項目。如何將此邏輯轉換爲LINQ語句?

因此,例如,列表包含具有類別1和2的項目。第一天(1/1)我將兩個項目發佈到類別1和2中。第二天(1/2)我將三個項目發佈到類別1.該列表應將第二天的發佈返回到類別1,並將第一天的發佈返回到類別2.

現在,我已將它按類別分組,然後運行foreach循環,以便將組中的每個項目與該組的最大日期,如果日期小於它刪除該項目的最大日期。

有一種方法可以把環路拿出來,但我還沒弄明白!

回答

2

你可以做這樣的事情:

from item in list 
    group item by item.Category into g 
    select g.OrderByDescending(it => it.CreationDate).First(); 

然而,這不是很有效,因爲它需要每一個組,這比需要的更復雜的項目進行排序(你實際上並不需要排序,你只需要掃描一次)。所以我創造了這個擴展方法與屬性的最大值(或功能)尋找項目:

from item in list 
    group item by item.Category into g 
    select g.WithMax(it => it.CreationDate); 

UPDATE:

public static T WithMax<T, TValue>(this IEnumerable<T> source, Func<T, TValue> selector) 
    { 
     var max = default(TValue); 
     var withMax = default(T); 
     var comparer = Comparer<TValue>.Default; 
     bool first = true; 
     foreach (var item in source) 
     { 
      var value = selector(item); 
      int compare = comparer.Compare(value, max); 

      if (compare > 0 || first) 
      { 
       max = value; 
       withMax = item; 
      } 
      first = false; 
     } 
     return withMax; 
    } 

您可以按如下方式使用它作爲安東尼在他的評論中指出,這段代碼並不完全回答這個問題......如果你想要所有日期是其類別的最大值的項目,你可以這樣做:

from item in list 
    group item by item.Category into g 
    let maxDate = g.Max(it => it.CreationDate) 
    select new 
    { 
     Category = g.Key, 
     Items = g.Where(it => it.CreationDate == maxDate) 
    }; 
+0

此代碼似乎只拉取類別中具有等於該類別的最大日期的類別中的第一項。問題是要求類別中的所有項目都是該類別的最大計數日期。 – 2010-05-29 21:49:19

+0

好點...我更新了我的答案 – 2010-05-29 22:03:50

+0

事實證明,你的代碼已經關閉了,但我的閱讀需求也是如此。儘管在我自己的批評中出現了錯誤,但第二次做得很好。 – 2010-05-29 22:14:36

1

如何:

private class Test 
    { 
     public string Category { get; set; } 
     public DateTime PostDate { get; set; } 
     public string Post { get; set; } 
    } 
    private void Form1_Load(object sender, EventArgs e) 
    { 
     List<Test> test = new List<Test>(); 
     test.Add(new Test() { Category = "A", PostDate = new DateTime(2010, 5, 5, 12, 0, 0), Post = "A1" }); 
     test.Add(new Test() { Category = "B", PostDate = new DateTime(2010, 5, 5, 13, 0, 0), Post = "B1" }); 

     test.Add(new Test() { Category = "A", PostDate = new DateTime(2010, 5, 6, 12, 0, 0), Post = "A2" }); 
     test.Add(new Test() { Category = "A", PostDate = new DateTime(2010, 5, 6, 13, 0, 0), Post = "A3" }); 
     test.Add(new Test() { Category = "A", PostDate = new DateTime(2010, 5, 6, 14, 0, 0), Post = "A4" }); 

     var q = test.GroupBy(t => t.Category).Select(g => new { grp = g, max = g.Max(t2 => t2.PostDate).Date }).SelectMany(x => x.grp.Where(t => t.PostDate >= x.max)); 
    } 
+0

這將計算類別中每個項目的類別的最大值......效率不高。您應該在Where過濾器之前計算最大值 – 2010-05-29 22:20:06

+0

@Thomas - 更改,謝謝。 – Luc 2010-05-29 23:23:23

0

重新格式化LUC的出色答卷查詢理解的形式。我更喜歡這種查詢方式,因爲範圍規則讓我可以更簡潔地編寫。

from item in source 
    group item by item.Category into g 
    let max = g.Max(item2 => item2.PostDate).Date 
    from item3 in g 
    where item3.PostDate.Date == max 
    select item3;