Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
388 views
in Technique[技术] by (71.8m points)

c# - Getting average value of groups with LINQ

I am trying to split my List into different groups based on a certain value each item in the List has, and then find the average of another value in those groups.

To better put it, I have a list of Students:

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 }
};

And I want to group them by their Class Level, so they'll be grouped into Freshman, Sophomore, Junior, and Senior. And then I want to be able to get the Average GPA for those groups.

So a possible result set for these students would be:

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

I'm not quite too sure how to go about getting this result though. I have tried things like students.GroupBy(x => x.Level).Average(); but it does not work.

Any thoughts on this would be greatly appreciated. Thank you!

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You have to use an additional Select, so you're looking for something like this:

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

Select(g => new {...}) creates an instance of a new anonymous type for each group.

That type has two properties:

  • Level, which is the Key property of the group
  • Avg, which is the average GPA of the group

Just "imagine" there's this type in use (more or less):

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) } );

but it simply has no name.


result is now:

enter image description here

Feel free to round the values if you need to.


To get the Level with the highest average, simply use

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

(Note that this will crash if there are no items in students)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...