问题
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