我们说我们有一个班级学生
class Student
{
public string Name { get; set; }
public string Gender { get; set; }
public List<string> Subjects { get; set; }
public static List<Student> GetAllStudetns()
{
List<Student> listStudents = new List<Student>
{
new Student
{
Name = "Tom",
Gender = "Male",
Subjects = new List<string> { "ASP.NET", "C#" }
},
new Student
{
Name = "Mike",
Gender = "Male",
Subjects = new List<string> { "ADO.NET", "C#", "AJAX" }
}
};
return listStudents;
}
}
我们想要打印每个学生这样的科目:
Tom - ASP.NET
汤姆 - C#
Mike - ADO.NET
迈克 - C#等
所以我找到的答案是
var result = Student.GetAllStudents().SelectMany(s => s.Subjects, (student, subject) => new { StudentName = student.Name, SubjectName = subject});
//then use foreach loop to retrieve...
我可以理解=&gt;的第二次使用,这只是对匿名类型的投影。但我不明白第一部分
s => s.Subjects, (student, subject)
根据我的理解,左侧=&gt;是intput参数,在这种情况下是Student实例s,但是右边的=&gt;应该是与Student实例相关的返回类型,例如s.Name,如果我们想获得学生的名字,那么(学生,主题)是什么意思?
答案 0 :(得分:2)
这是因为Subjects
在类中被定义为List<string>
,你必须单独打印它,所以它需要迭代子列表的集合。在解释查询的请求部分(s => s.Subjects, (student, subject)
)之前,您应该先了解.SelectMany
public static IEnumerable<TResult> SelectMany<TSource, TResult>(
this IEnumerable<TSource> source,
Func<TSource, IEnumerable<TResult>> selector
)
根据方法的签名,第二个参数(Func
)接受源对象(此处为Student
类型)和IEnumerable
个集合对象,此处为是字符串类型,因为它是List<string>
。
这意味着(student, subject)
中的学生属于Student
类型且主题将是s.Subjects
中的项目,因此.SelectMany
将进一步遍历子集合。< / p>
如果你想这样打印(Tom - ASP.NET,C#
)意味着你可以在你的情况下做GroupBy
你不想这样做,所以使用该代码对子列表进行迭代;
其他信息:如果结果基于分组,那么您的代码将如下所示:
var result = Student.GetAllStudents()
.GroupBy(s => s.Name)
.Select(x=> new { StudentName = x.Key, SubjectName = String.Join(",",
x.SelectMany(y=>y.Subjects)
.ToList()});
答案 1 :(得分:2)
SelectMany已超载。见https://msdn.microsoft.com/en-us/library/bb534631(v=vs.110).aspx
s => s.Subjects
是您的集合选择器 - 将应用于输入
和(student, subject) => new { StudentName = student.Name, SubjectName = subject}
是你的结果选择器 - 应用于中间序列的每个元素的转换函数