2015-02-10 110 views
5

我想根據列表中每個項目的某個值將我的列表分成不同的組,然後在這些組中找到另一個值的平均值。獲取LINQ組的平均值

爲了更好地穿上它,我的學生名單:

List<Student> students = new List<Student> { 
    new Student { Name="Bob", Level=Level.Sophomore, GPA=3.2f }, 
    new Student { Name="Cathy", Level=Level.Freshman, GPA=3.6f }, 
    new Student { Name="James", Level=Level.Senior, GPA=3.8f }, 
    new Student { Name="Jessica", Level=Level.Senior, GPA=3.7f }, 
    new Student { Name="Derek", Level=Level.Junior, GPA=2.8f }, 
    new Student { Name="Sam", Level=Level.Junior, GPA=3.1f } 
}; 

而且我想他們按自己的職業等級,所以他們將被分爲大一,大二,大三,和高級。然後我希望能夠獲得這些羣體的平均GPA。

所以這些學生可能的結果集是:

Senior: 3.7 
Junior: 2.9 
Sophomore: 3.2 
Freshman : 3.6 

我不太不太清楚如何去得到,雖然這個結果。我嘗試過像students.GroupBy(x => x.Level).Average();之類的東西,但它不起作用。

對此的任何想法將不勝感激。謝謝!

回答

13

你必須使用一個額外的Select,所以你正在尋找的東西是這樣的:

var result = students.GroupBy(s => s.Level) 
        .Select(g => new {Level=g.Key, Avg=g.Average(s => s.GPA)}); 

Select(g => new {...})創建一個新的匿名類型爲每個組的一個實例。

這種類型有兩個屬性:

  • Level,這是該集團
  • Avg,這是該集團的平均GPA

只是 「想象」 的Key財產有這種類型在使用(或多或少):

class GroupAverage 
{ 
    public Level Level { get; set; } 
    public float Avg { get; set; } 
} 

var result = students.GroupBy(s => s.Level) 
        .Select(g => new GroupAverage { Level=g.Key, Avg=g.Average(s => s.GPA) }); 

但它根本沒有名字。


result現在是:

enter image description here

隨意,如果您需要四捨五入的值。


要獲得Level最高平均,只需使用

var highest = result.OrderByDescending(a => a.Avg).First().Level; 

(請注意,如果在students沒有項目,這將崩潰)

+0

你能解釋一下這個查詢在做什麼嗎?我不太瞭解新的{Level = g.Key,Avg = g.Average(s => s.GPA)}。 – user3113376 2015-02-10 08:11:04

+0

他正在從他的前一組中選擇一個匿名對象,並具有2個屬性:1.分組的關鍵字,即關卡。第二個屬性是分組中的一個聚合,在這種情況下,他將該分組中的所有學生GPA的平均值。 – Marco 2015-02-10 08:13:24

+0

按Level分組,然後選擇包含兩個值的新匿名對象,鍵值(由group()函數生成)和GPA的平均值。 – Luke 2015-02-10 08:14:13

0

檢查了這一點:

students.GroupBy(s => s.Level, s => s.GPA, 
       (level, scores) => new { Level = level, Avg = scores.Average() }