C# List 加入列表并从另一个列表中过滤

标签 c# linq

需要一些帮助来使用连接构建正确的 LINQ 查询。

我有以下设置:

public class Student
{
    public string StudentName { get; set; }
    public string StudentEmail { get; set; }
}

public class Enrolled
{
    public Student Student { get; set; }
    public string Subject { get; set; }
}

public class Dropped
{
    public Student Student { get; set; }
    public string Subject { get; set; }
}


// Populating the List.
// Setup the Student List
List<Student> lstStudents = new List<Student>();

var John = new Student()
{
    StudentEmail = "john@stanford.edu",
    StudentName = "John Wayne"
};

var Maya = new Student()
{
    StudentEmail = "maya@stanford.edu",
    StudentName = "Maya Agnes"
};

var Eric = new Student()
{
    StudentEmail = "eric@stanford.edu",
    StudentName = "Eric James"
};

var Ellen = new Student()
{
    StudentEmail = "ellen@stanford.edu",
    StudentName = "Ellen Page"
};

lstStudents.Add(John);
lstStudents.Add(Maya);
lstStudents.Add(Eric);
lstStudents.Add(Ellen);

// Setup the Enrolled List
List<Enrolled> lstEnrolled = new List<Enrolled>();

// John
var JohnMath = new Enrolled() { Student = John, Subject = "Math" };
var JohnScience = new Enrolled() { Student = John, Subject = "Science" };
var JohnEnglish = new Enrolled() { Student = John, Subject = "English" };

// Maya
var MayaMath = new Enrolled() { Student = Maya, Subject = "Math" };

// Eric
var EricMath = new Enrolled() { Student = Eric, Subject = "Math" };
var EricScience = new Enrolled() { Student = Eric, Subject = "Science" };
var EricSocial = new Enrolled() { Student = Eric, Subject = "Social" };

// Ellen
var EllenMath = new Enrolled() { Student = Ellen, Subject = "Math" };
var EllenScience = new Enrolled() { Student = Ellen, Subject = "Science" };
var EllenEnglish = new Enrolled() { Student = Ellen, Subject = "English" };
var EllenSocial = new Enrolled() { Student = Ellen, Subject = "Social" };

lstEnrolled.Add(JohnMath);
lstEnrolled.Add(JohnScience);
lstEnrolled.Add(JohnEnglish);
lstEnrolled.Add(MayaMath);
lstEnrolled.Add(EricMath);
lstEnrolled.Add(EricScience);
lstEnrolled.Add(EricSocial);
lstEnrolled.Add(EllenMath);
lstEnrolled.Add(EllenScience);
lstEnrolled.Add(EllenEnglish);
lstEnrolled.Add(EllenSocial);

// Setup the Dropped List
List<Dropped> lstDropped = new List<Dropped>();

// John dropped Math
var JohnDropMath = new Dropped() { Student = John, Subject = "Math" };

// Eric dropped Social
var EricDropSocial = new Dropped() { Student = Eric, Subject = "Social" };

// Ellen Dropped Math
var EllenDropMath = new Dropped() { Student = Ellen, Subject = "Math" };

lstDropped.Add(JohnDropMath);
lstDropped.Add(EricDropSocial);
lstDropped.Add(EllenDropMath);

我想要实现的是获取所有学生的列表,以及他们在一行中注册的科目,例如:

Student     Subjects
-------     ----------------------------------
John        English, Science
Maya        Math
Eric        Math, Science
Ellen       English, Science, Social   

到目前为止,我已经构建了以下内容:

var StudentsAndCurrentSubjects = (from st in lstStudents
                                  join en in lstEnrolled 
                                      on st.StudentName equals en.Student.StudentName
                                  select new
                                  {
                                      st.StudentName,
                                      en.Subject
                                  })
                                  .ToList();

但它给出了每个人每个主题的结果。

我在如何从列表中排除掉落的项目时碰壁了。

我正在考虑遍历 dropped 列表,例如:

foreach(d in lstDropped) 
{
    // Logic to Remove it from the StudentsAndCurrentSubjects 
}

但我觉得它效率低下(尤其是当我有很多行时)。

我也不知道如何在一行中加入主题。

在这里寻求帮助。

谢谢。

最佳答案

我们只需要先从注册列表中删除删除的主题。然后按学生分组。 请注意,我们有每个学生的列表,它有 StudentSubject 作为其字段,我们只需从每个学生中选择第一个学生的名字(因为它们都一样)并将主题连接在一起。

var result = lstEnrolled.Where(e => !lstDropped.Any(d => d.Student == e.Student && d.Subject == e.Subject))  //omit dropped courses
     .GroupBy(x => x.Student) // group results by students
     .Select(x => new {
            Name = x.First().Student.StudentName.Split(' ').First(), 
            Subjects = string.Join(", ", x.Select(e => e.Subject)) 
       }).ToArray();

用于打印:

foreach(var x in result)
Console.WriteLine($"{x.Name}\t{x.Subjects}");

LIVE DEMO

关于C# List 加入列表并从另一个列表中过滤,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52449193/

相关文章:

c# - SQL Server 始终在插入时加密排序规则不兼容

c# - 在 linq 中将 int 转换为字符串以进行搜索

c# - 使用 LINQ to SQL 计算日期时间

c# - 求一个Winforms System.ComponentModel.Design Design Surface BeginDrag/EndDrag事件钩子(Hook)

c# - 如何在运行时向方法添加属性?

C# JSON 解析

c# - 如何使用 nhibernate 和 LINQ 将多个连接(获取)添加到连接表?

c# - int' 不包含 'contains' 的定义,并且找不到接受类型为 'contains' 的第一个参数的扩展方法 'int'

c# - Nhibernate 3 Linq 抛出 Antlr.Runtime.NoViableAltException

c# - json.net 在 77kb json 字符串上的性能