使用Linq用这两个对象创建扁平列表的最佳方法是什么
public class DataDto
{
public string StudentID { get; set; }
public List<ScoreDto> Scores { get; set; }
}
public class ScoreDto
{
public string ExamID { get; set; }
public double Mark { get; set; }
}
将放入列表中,该列表将显示为
public class FinalDto
{
public string StudentID { get; set; }
public string ExamID { get; set; }
public double Mark { get; set; }
}
用StudentID
的重复次数表示某一特定学生ScoreDtos
的出现次数。
示例数据-
var data = new List<DataDto>()
{
new DataDto
{
StudentID = "S1",
Scores = new List<ScoreDto>()
{
new ScoreDto { ExamID = "01", Mark = 5},
new ScoreDto { ExamID = "02", Mark = 15},
new ScoreDto { ExamID = "03", Mark = 25}
}
},
new DataDto
{
StudentID = "S2",
Scores = new List<ScoreDto>()
{
new ScoreDto { ExamID = "01", Mark = 1},
new ScoreDto { ExamID = "02", Mark = 5},
new ScoreDto { ExamID = "03", Mark = 20}
}
}
};
生成-
StudentID, ExamID, Mark
S1, 01, 5
S1, 02, 15
S1, 03, 25
S2, 01, 1
S2, 02, 5
S2, 03, 20
您使用SelectMany
来平化列表的列表:
var final = data.SelectMany(
student => student.Scores,
(student, score) => new FinalDto {
StudentID = student.StudentID,
ExamID = score.ExamID,
Mark = score.Mark
}
);
Console.WriteLine("StudentID, ExamID, Mark");
foreach (var result in final)
{
Console.WriteLine("{0}, {1}, {2}", result.StudentID, result.ExamID, result.Mark);
}
或者,您可以使用SelectMany
的不同重载以及嵌套的Select
投影:
var final = data.SelectMany(
student => student.Scores.Select(
score => new FinalDto {
StudentID = student.StudentID,
ExamID = score.ExamID,
Mark = score.Mark
}
)
);
您也可以使用查询语法:
var final = (
from student in data
from score in student.Scores
select new FinalDto {
StudentID = student.StudentID,
ExamID = score.ExamID,
Mark = score.Mark
}
);
注意,这只是转换成上面所示的第二种形式。
没有"最佳"在这里。表单2和表单3可以编译成完全相同的代码。形式一只是一个小小的变化。选择一个而不是另一个没有影响(速度、内存)。选择一个视觉上吸引你的。就我个人而言,我不写查询语法(最后一种形式),我总是忘记第一个重载存在,所以我最终使用第二个。
var result = (
from item in data
from score in item.Scores
select new FinalDto {
StudentID = item.StudentID,
ExamID = score.ExamID,
Mark = score.Mark
}).ToList();
有两个一对多关系的表:表a的每一项都有0个或多个来自表B的项,并且表B的每一项都只属于表a的一个项,即外键所指向的一个项。
当你有了这个,并且你想要"项及其子项",比如学校及其学生,客户及其订单,作者及其图书,考虑使用Queryable重载之一。GroupJoin
如果您不想要包含子项的项,而是一个平面表,请考虑使用Queryable。加入
显然,您已经获取了"分数为零或更高的学生",并且您想要一个平坦的结果。在这种情况下,使用SelectMany
IEnumerable<DataDto> studentsWithTheirScores = ...
var result = studentsWithTheirScores.SelectMany(
// parameter collectionSelector: where are the sub-items stored?
student => student.Scores,
// parameter resultSelector: take each student, and each one of his Scores
// to make one new
(student, score) => new FinalDto
{
StudentId = student.StudentId,
ExamId = score.ExamId,
Mark = score.Mark,
});