[英]How can I aggregate two List in some operation by using Linq?
我已經定義了類 StudentData ,它包含 Name、Subject 屬性,它們是 Enum 類型,分數為 double。 一些數據填充在List結構StudentNameList和StudentDataList中。
public class StudentData
{
public StudentName Name { get; set; }
public Subject Subject { get; set; }
public double Score { get; set; }
public StudentData(StudentName name, Subject subject, double score)
{
Name = name;
Subject = subject;
Score = score;
}
}
public enum StudentName
{
Tom,
Nikki,
Benny
}
public enum Subject
{
Math,
Physic,
History
}
List<StudentName> studentName = new List<StudentName>();
studentName.Add( StudentName.Benny);
studentName.Add(StudentName.Nikki);
studentName.Add(StudentName.Tom);
List<StudentData> studentDataList = new List<StudentData>();
studentDataList.Add(new StudentData(StudentName.Benny, Subject.History, 85));
studentDataList.Add(new StudentData(StudentName.Benny, Subject.Math, 60));
studentDataList.Add(new StudentData(StudentName.Benny, Subject.Physic, 75));
studentDataList.Add(new StudentData(StudentName.Nikki, Subject.History, 65));
studentDataList.Add(new StudentData(StudentName.Nikki, Subject.Math, 70));
studentDataList.Add(new StudentData(StudentName.Nikki, Subject.Physic, 75));
studentDataList.Add(new StudentData(StudentName.Tom, Subject.History, 88));
studentDataList.Add(new StudentData(StudentName.Tom, Subject.Math, 90));
studentDataList.Add(new StudentData(StudentName.Tom, Subject.Physic, 95));
下面定義了因子表
List<double> FactorTable = new List<double>();
FactorTable.Add(1.05);
FactorTable.Add(1.02);
我想要實現的是創建一個 Dictionary<StudentName, Double> ,該值存儲該學生的所有加權平均分數(乘以所有分數和因子列表)。 例如在本尼的情況下:
Dictionary<StudentName, double> StudentDic = new Dictionary<StudentName, double>();
鍵:本尼,值:(85 * 1.05) + (85 * 1.02) + (60 * 1.05) + (60 * 1.02) + (75 * 1.05) + (75 * 1.02)
我認為它可以通過少數聚合 Linq 操作來完成。 然而,當我開始實施時,它並不那么容易實現。 我所做的如下:
foreach (var student in studentName)
{
var filterStudent = studentDataList.Where(s => s.Name == student);
List<double> multipledResult = new List<double>();
foreach (var s in filterStudent)
{
foreach (var f in FactorTable)
{
multipledResult.Add(s.Score * f);
}
}
StudentDic.Add(student, multipledResult.Average());
}
通過使用 Linq 操作來簡化算法,我錯過了什么。 有人可以建議是否有辦法改進它?
這應該給你一個起點:
var result =
studentDataList
.SelectMany(sdl => FactorTable.Select(ft => new {
sdl.Name,
aggScore = ft * sdl.Score
}))
.GroupBy(prod => prod.Name)
.Select(g => new {
Name = (StudentName)g.Key,
wtAvg = g.Sum(x => x.aggScore) / g.Sum(x => x.ft)
})
.ToDictionary(x => (StudentName)x.Name, x => x.wtAvg);
SelectMany -> Select
方法通過每個權重為您提供每個分數的目標產品。 然后鏈為每個人創建一個組。 最后的Select
匯總了組中的所有加權產品。 如果您真的需要,最后一行會將其轉換為字典。
但不要忘記,對於加權平均,您還想除以可能的總權重。
它給出了結果:
| Benny | 73.333... |
| Nikki | 70 |
| Tom | 91 |
本尼的分數基本上是通過以下方式得出的:
var num = (85 * 1.05) + (85 *1.02) + (60 * 1.05) + (60 * 1.02) + (75 * 1.05) + (75 * 1.02);
var den = 1.05 + 1.02 + 1.05 + 1.02 + 1.05 + 1.02;
var result = num / den; // 73.33333......
當然,如果您真的想要加權總和,而不是加權平均值,那么只需刪除最終選擇方法中的分母並將其從wtAvg
重命名為wtSum
。
正如@pwilcox 提到的, SelectMany
是典型 LINQ 處理結果的關鍵,但我建議先分組,然后計算:
var StudentDic = studentDataList.GroupBy(s => s.Name, s => s.Score)
.ToDictionary(sg => sg.Key,
sg => sg.SelectMany(s => FactorTable.Select(f => s*f)).Average());
請注意,您可以通過對學生的分數求和,將總和乘以每個因素,然后將總和除以分數計數乘以因素計數來避免SelectMany
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.