为什么分组加入的结果重复2次?

时间:2019-06-06 16:51:22

标签: c# linq

我在2个收藏夹之间编写了分组联接 1名学生 2马德拉克 每个madrak有很多学生,每个学生都有一个madrak 换句话说,表之间存在一对多的关系

分组加入的结果是 ![group join]:({https://pasteboard.co/IibmzbL.jpg

重复2次。 我不明白为什么我们有4个小组

namespace ConsoleApp4{
class Program
{
   static void Main(string[] args)
    {
        IList<Student> studentList = new List<Student>()
                                {
                                new Student() { StudentID = 1, StudentName 
                                  = "davod zarei", MadrakID =1 },
                                new Student() { StudentID = 2, StudentName 
                                = "eshrat alipour", MadrakID =1 },
                                new Student() { StudentID = 3, StudentName 
                                = "hadi pournader", MadrakID =2 },
                                new Student() { StudentID = 4, StudentName 
                                = "mahdi chegini", MadrakID =2 },
                                new Student() { StudentID = 5, StudentName 
                                 = "Bozorg Mirzahoseini"}
                               };
        IList<Madrak> madrakList = new List<Madrak>()
                                {
                                new Madrak(){ MadrakID = 1, 
                                 MadrakName="lisance"},
                                new Madrak(){ MadrakID = 2, 
                                MadrakName="arshad"},
                                new Madrak(){ MadrakID = 3, 
                                MadrakName="phd"},
                                };
       var GroupJoinResult2 =
             from md in madrakList
             join  stu in studentList
             on md.MadrakID  equals stu.MadrakID into MachedStudent
             from item in MachedStudent
             select new { Key = md.MadrakID, Items = MachedStudent };
      Console.WriteLine("---------- group Join  Result ----------");
      foreach (var item in GroupJoinResult2)
        {
            Console.WriteLine(item.Key + ":");
            foreach (var element in item.Items)
            {
                Console.WriteLine("   " + element.StudentName);
            }
        }

        Console.ReadKey();
        }
    }
public class Student
{
    public int StudentID { get; set; }
    public string StudentName { get; set; }
    public int MadrakID { get; set; }
}

public class Madrak
{
    public int MadrakID { get; set; }
    public string MadrakName { get; set; }
}
}

1 个答案:

答案 0 :(得分:6)

  

我不明白为什么我们有4个小组

通过将一组学生与一个学生混淆,您将组加入和常规加入做了一个非常奇怪的组合。

让我们详细了解一下。

我将简化您的代码。让我们从简化学生类型开始:

public class Student
{
    public Student(string s, string m) 
    {
        StudentName = s;
        MadrakName = m;
    }
    public string StudentName { get; set; }
    public string MadrakName { get; set; }
    public override string ToString() { return StudentName; }
}

学校可以只是一串绳子。所以现在我们有四个学生和三个学校:

    var studentList = new List<Student>() {
        new Student("S1", "M1"),
        new Student("S2", "M1"),
        new Student("S3", "M2"),
        new Student("S4", "M2")
    };
    var madrakList = new List<string>() { "M1", "M2", "M3" };

第三所学校没有学生。

我们想要什么?我们想要每个学校的学生名单。就是说,我们应该得到三个清单。第一个列表应该是S1和S2,第二个应该是S3和S4,第三个应该为空:

    var q =
         from m in madrakList
         join s in studentList
         on m equals s.MadrakName into MatchedStudent
         select MatchedStudent;

现在让我们打印出每个:

   foreach(var item in q)
       Console.WriteLine("{" + string.Join(",", item) + "}");

我们得到了想要的东西:

{S1,S2}
{S3,S4}
{}

有3所学校,所以您的小组参加活动应该有3行。

现在,为什么要获得查询所得到的结果? 您已将群组加入重新设置为常规加入。让我们尝试对您的查询进行修改:

         from m in madrakList
         join s in studentList
         on m equals s.MadrakName into MatchedStudent
         from item in MatchedStudent
         select new { Key = m, Items = item };

item取值S1,S2,S3,S4,这表示创建一个元组,其中键是学校,m,项是学生。您所做的只是一种非常复杂的书写方式

         from m in madrakList
         join s in studentList
         on m equals s.MadrakName 
         select new { Key = m, Items = s }

即普通联接,而不是组联接。显然有四行,因为它们是:

M1, S1
M1, S2
M2, S3
M2, S4

有四名学生在上学,所以您的普通加入应有四行。

但这不是您写的。你写了

         from m in madrakList
         join s in studentList
         on m equals s.MadrakName into MatchedStudent
         from item in MatchedStudent
         select new { Key = m, Items = MatchedStudent }; 
         // MatchedStudent is a list of students!

那么,你现在得到了什么?代替

M1, S1
M1, S2
M2, S3
M2, S4

在该列中有一个学生的地方,相反,在该列中有所有匹配的学生:

M1, {S1, S2} // From S1
M1, {S1, S2} // From S2
M2, {S3, S4} // From S3
M2, {S3, S4} // From S4

基本上,您已经编写了一个非常奇怪的组合,包括常规联接和组联接。该表格采用常规联接的形式,分为四行,每行一所学校,每个学生一个,但是该行中的每个“学生”都是该组中匹配的学生的整个列表。 >

您似乎很困惑,并且忘记了MatchedStudent是学生的列表,因为它是组加入。您像对待学生一样对待它,但这也是错误的。

可能您打算编写的代码是:

    var q =
         from m in madrakList
         join s in studentList
         on m equals s.MadrakName into studentsInMadrak
         select new { Madrak = m, Students = studentsInMadrak };
   foreach(var item in q)
       Console.WriteLine(item.Madrak + "{" +  
         string.Join(",", item.Students) + "}");

哪个打印出来

M1{S1,S2}
M2{S3,S4}
M3{}

这一切有意义吗?