简体   繁体   English

如何使用LINQ计算列表中每个项目的平均值?

[英]how to calculate average for each item in a list with LINQ?

How can I calculate each of the averages of the students?如何计算每个学生的平均分? I did this ... but the average does not work for me, how could I do it?我这样做了......但平均值对我不起作用,我怎么做? With a JoinGroup and then a GroupBy ?, I wait to see solutions, thanks.使用 JoinGroup 和 GroupBy ?,我等着看解决方案,谢谢。

var listadoA = alumnos.Join(examenes, 
                        a => a._id,
                        e => e._alumnoId,
                        (a, e) => new
                        {
                            NombreAlumno = a._nombre,
                            Examenes = examenes,
                            Notas = e._nota,
                        }).Where(p => p.Examenes.Count() >= 1).OrderBy(p => p.NombreAlumno).ToList();
        foreach (var obj in listadoA){
            var promedio = obj.Average(p => p.Nota);
            Console.Write($"\nAlumno = {obj.NombreAlumno}, Promedio ={promedio}");
        }   


class Examen{
    public double _nota{get;set;}
    public int _alumnoId {get;set;}
    public int cursoId{get;set;}


    public Examen(int id, double nota, int idMateria){
        this._alumnoId = id;
        this.cursoId = idMateria;
        this._nota = nota;
    }

    public override string ToString(){
        return ($"Alumno = {this._alumnoId}, Nota = {this._nota}, Curso = {this.cursoId}");
    }
    public static List<Examen> GetLista(){
        return new List<Examen>(){
            new Examen(2,5,1),
            new Examen(4,7,5),
            new Examen(4,9,3),
            new Examen(3,10,4),
            new Examen(7,5,3),
            new Examen(2,8,4),
            new Examen(6,9,5),
            new Examen(9,7,1),
            new Examen(6,5,4),
            new Examen(9,1,4),
            new Examen(7,9,5),
        };
    }
}

I'm a bit short on time to test it but I think it should work with a few small tweaks.我的测试时间有点短,但我认为它应该通过一些小的调整来工作。 If I've made any typos, let me know:如果我有任何错别字,请告诉我:

var listadoA = alumnos.GroupJoin(examenes, 
                    a => a._id,
                    e => e._alumnoId,
                    (a, eGroup) => new
                    {
                        Alumno = a,
                        Examenes = eGroup
                        
                    }).Where(p => p.Examenes.Count() >= 1).OrderBy(p => p.Alumno._nombre).ToList();
foreach (var obj in listadoA){
        var promedio = obj.Examenes.Average(e => e._nota);

I'm curious why your fields starting with underscore are publicly accessible;我很好奇为什么您的以下划线开头的字段可以公开访问; that's the naming convention for a private field.. should really have public properties for them.这是私有字段的命名约定.. 应该真正为它们提供公共属性。 Also, I've assumed that "nota" is the exam score..另外,我假设“nota”是考试成绩。

EDIT编辑

The answer was originaly posted before precisions were made about the classes involved.答案最初是在对所涉及的类进行精确处理之前发布的。 I still keep the english naming, because it might be clearer for a wider audience.我仍然保留英文命名,因为它可能对更广泛的受众更清晰。 This also helps clarify my answer in regards to @Caius Jard pertinent comment.这也有助于澄清我对@Caius Jard 相关评论的回答。

Using Linq to object: (no use of Entity Framework)使用 Linq 对象:(不使用实体框架)

This code does the following tradeof compared to the use of join.与使用 join 相比,此代码执行以下权衡。 It might be less performant, but it is more simple (you don't even have to understand what a join is).它的性能可能较差,但更简单(您甚至不必了解联接是什么)。

AveragesByStudents = Students
    .Select(s => new 
    {
        StudentName = s.Name,
        Notes = Exams
            .Where(e => e.StudentId == s.Id)
            .Select(e => e.Note)
            .ToList()
    })
    .Select(s => new 
    {
        s.StudentName,
        Average = s.Notes.Any() ? s.Notes.Average() : null
    });
;

With this example, you obtain all the students, even if they have no notes (in that case their average is null).在此示例中,您可以获得所有学生,即使他们没有笔记(在这种情况下,他们的平均值为空)。 You could do it in one select, but it would not be more readable.您可以在一个选择中完成它,但它不会更具可读性。

With the following example, you obtain only the students that have notes, so their average cannot be null.在以下示例中,您仅获取有笔记的学生,因此他们的平均值不能为空。

AveragesByStudents = Students
    .Select(s => new 
    {
        StudentName = s.Name,
        Notes = Exams
            .Where(e => e.StudentId == s.Id)
            .Select(e => e.Note)
    })
    .Where(s => s.Notes.Any())
    .Select(s => new 
    {
        s.StudentName,
        Average = Notes.Average()
    });
;

Add a ToList() at the end of queries if you want to materialize.如果要实现,请在查询末尾添加 ToList()。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM