Linq to group by two fields and average

倖福魔咒の 提交于 2021-01-20 13:07:07

问题


I have the following C# models:

public class RawData
{
    public int questionnaireId { get; set; }

    public int coachNodeId { get; set; }

    public int questionnaireNumber { get; set; }

    public float score { get; set; }
}

public class AveragedData
{
    public int coachNodeId { get; set; }

    public int questionnaireNumber { get; set; }

    public float averageScore { get; set; }
}

I have an API endpoint which is returning data from a database, mapped as List<RawData>. The values are like this:

questionnaireId | coachNodeId | questionnaireNumber | score
1               | 30          | 1                   | 2
2               | 40          | 1                   | 3
3               | 30          | 2                   | 1
4               | 30          | 3                   | 4
5               | 40          | 2                   | 5
6               | 40          | 1                   | 5
7               | 30          | 1                   | 1
8               | 30          | 1                   | 2
9               | 40          | 1                   | 2
10              | 30          | 2                   | 4

What I need to do now, in a LINQ query, is to average out the score values grouped by coachNodeId and questionnaireNumber and return a list of type AveragedData.

The values returned by averaging and grouping the example data above, should be:

coachNodeId | questionnaireNumber | averageScore
30          | 1                   | 1.66666666          (calculated by: (2 + 1 + 2) / 3))
30          | 2                   | 2.5                 (calculated by: (1 + 4) / 2))
30          | 3                   | 4                   (calculated by: (4 / 1))
40          | 1                   | 3.33333333          (calculated by: (3 + 5 + 2) / 3))
40          | 2                   | 5                   (calculated by: (5 / 1))

I'm not experienced with LINQ so am struggling to put together a query that groups by both coachNodeId and questionnaireNumber and averages the score, returning an object of type List<AveragedData>. Could anyone suggest how to accomplish this?

Many thanks.


回答1:


assuming you have a List<RawData> called list, you are wanting:

var results = list.GroupBy(x => new
                                {
                                     questionnaire = x.questionnaireId,
                                     coach = x.coachNodeId
                                })
                  .Select(x => new AveragedData
                                {
                                     coachNodeId = x.Key.coach,
                                     questionnaireNumber = x.Key.questionnaire,
                                     averageScore = x.Average(xx => xx.score)
                                })
                  .ToList();

Do the grouping, then use a Select to project the data to your type, using LINQ's Average as well.




回答2:


Try following :

            DataTable dt = new DataTable();
            dt.Columns.Add("questionnaireId", typeof(int));
            dt.Columns.Add("coachNodeId", typeof(int));
            dt.Columns.Add("questionnaireNumber", typeof(int));
            dt.Columns .Add("score", typeof(int));

            dt.Rows.Add(new object[] {1,30, 1, 2});
            dt.Rows.Add(new object[] {2,40, 1, 3});
            dt.Rows.Add(new object[] {3,30, 2, 1});
            dt.Rows.Add(new object[] {4,30, 3, 4});
            dt.Rows.Add(new object[] {5,40, 2, 5});
            dt.Rows.Add(new object[] {6,40, 1, 5});
            dt.Rows.Add(new object[] {7,30, 1, 1});
            dt.Rows.Add(new object[] {8,30, 1, 2});
            dt.Rows.Add(new object[] {9,40, 1, 2});
            dt.Rows.Add(new object[] {10,30, 2, 4});

            var averages = dt.AsEnumerable()
                .GroupBy(x => new { coachNodeId = x.Field<int>("coachNodeId"), questionnaireNumber = x.Field<int>("questionnaireNumber") })
                .Select(x => new { coachNodeId = x.Key.coachNodeId, questionnaireNumber = x.Key.questionnaireNumber, average = x.Average(y => y.Field<int>("score")) })
                .ToList();


来源:https://stackoverflow.com/questions/64486592/linq-to-group-by-two-fields-and-average

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!