找到linq的平均最大值

时间:2016-07-29 20:52:43

标签: c# linq

我有一个List = new List();

public class Student
{
    public string Id { get; set; }
    public string name { get; set; }
    public string subject { get; set; }
    public string marks { get; set; }
}

我的目标

找到平均成绩最高的学生

添加数据样本

i.Add(new List<Student> { Id=1,Name= "Maddy",Subject="English",Marks=87 };
i.Add(new List<Student> { Id=1,Name= "Maddy",Subject="Science",Marks=81 };
i.Add(new List<Student> { Id=2,Name= "Mathew",Subject="Maths",Marks=83 };
i.Add(new List<Student> { Id=2,Name= "Mathew",Subject="Science",Marks=80 };

我尝试了什么

var x=  i.GroupBy(i=>i.Id)
         .Select( g=> new 
                     { 
                       MaxAverage= g.Max(g.Average(i=>i.Marks))  
                      } 

4 个答案:

答案 0 :(得分:2)

最佳学生

var best = i.GroupBy(g => g.Id)
            .Select(g => new { 
                StudentID = g.Key, 
                Name = g.First().Name, 
                Average = g.Average(m => m.Marks), 
                })
            .OrderByDescending(g => g.Average)
            .First();
// best = { StudentID = 1, Name = Maddy, Average = 84 }

最佳平均值

var best = i.GroupBy(g => g.Id)
            .Select(g => g.Average(m => m.Marks))
            .Max();
// best = 84.0

查询语法(仅仅因为)

var best = (from student in 
                from grade in grades 
                group grade by grade.Id
             select student.Average(mark=>mark.Marks)).Max();    
// best = 84.0

没有LINQ (我看到一条评论建议你这样做......哎哟)

var dict = new Dictionary<int, List<double>>();
foreach (var g in i )
{
    var id = g.Id;
    if (!dict.ContainsKey(id))
        dict.Add(id, new List<double>());
    dict[id].Add(g.Marks);
}
double best = 0.0;
foreach (var g in dict)
{
    var totalmarks = 0.0;
    foreach (var mark in g.Value)
    {
        totalmarks += (double)mark;
    }
    var average = totalmarks / g.Value.Count;
    if (best < average)
        best = average;
}
// best = 84.0

没有LINQ(略微优化)

var dict = new Dictionary<int, Tuple<int, double>>();
foreach (var g in i)
{
    var id = g.Id;
    Tuple<int, double> t;
    if (!dict.ContainsKey(id))
        dict.Add(id, t = Tuple.Create(0, 0.0));
    else
        t = dict[id];
    var c = t.Item1 + 1;

    dict[id] =  Tuple.Create(c, (t.Item2 * t.Item1 + g.Marks) / c);
}
double best = 0.0;
foreach (var g in dict)
{
    var m = g.Value.Item2;
    if (best < m)
        best = m;
}
// best = 84.0

答案 1 :(得分:2)

  • 使用Linq“查询语法”

    var best = from student in students
               group student by student.Id into studentAverage
               let average = studentAverage.Average (s => s.Marks)
               orderby average descending
               select new { id = studentAverage.Key, average };
               // change projection to have only id or average
    
  • 使用Linq“方法语法”

    var best =
        students
        .GroupBy (student => student.Id,
                  student => student.Marks,
                  (id, marks) => new { id, average = marks.Average () })
        .OrderByDescending (studentAverage => studentAverage.average)
        // add a projection (Select) here to have only id or average
        .FirstOrDefault ();
    

    也许更简单的选择,但更倾向于只获得Id

    var best =
        students
        .ToLookup (s => s.Id, s => s.Marks)
        .OrderByDescending (marksById => marksById.Average ())
        .FirstOrDefault ();
    
    // Key will contain the Id but Average must be calculated again
    // var avg = best.Average();
    
  • 使用“经典”代码(更长但更清晰的步骤)

    var studentMarks = new Dictionary<int, List<double>> (students.Count);
    
    foreach (var student in students)
    {
        int id = student.Id;
        List<double> marks;
    
        if (!studentMarks.TryGetValue (id, out marks))
        {
            marks = new List<double> ();
            studentMarks.Add (id, marks);
        }
    
        marks.Add (student.Marks);
    }
    
    double? bestAverage = null;
    int? idOfBest = null;
    
    foreach (var idAndMarks in studentMarks)
    {
        var average = 0.0;
    
        foreach (var mark in idAndMarks.Value)
        {
            average += mark;
        }
    
        average /= idAndMarks.Value.Count;
    
        if (average > bestAverage)
        {
            bestAverage = average;
            idOfBest = idAndMarks.Key;
        }
    }
    

答案 2 :(得分:0)

var i = new List<Student>();

i.Add(new Student { Id = 1, Name = "Maddy", Subject = "English", Marks = 87 });
i.Add(new Student { Id = 1, Name = "Maddy", Subject = "Science", Marks = 81 });
i.Add(new Student { Id = 2, Name = "Mathew", Subject = "Maths", Marks = 83 });
i.Add(new Student { Id = 2, Name = "Mathew", Subject = "Science", Marks = 80 });


var students = i.GroupBy(p => p.Id).ToDictionary(group => group.Key, group => group.Select(p => p.Marks).Average());
var maxStudent = students.Aggregate((l, r) => l.Value > r.Value ? l : r).Key;

答案 3 :(得分:0)

这样的东西?

 var bestStudent = i.GroupBy(i=>i.Id)
    .Select( g=> new Student 
    { 
        Id = g.Key, 
        Name = g.First().Name, 
        Marks = g.Average(i=>i.Marks)) 
    })
    .OrderByDescending(s => s.Marks)
    .FirstOrDefault();