如何使用 LINQ 有效地从两个列表中选择某些项



>我有这 3 个类:

  • 员工
  • 学生

法典:

public class Employee
{
    public Guid Id { get; set; }
    public string Name { get; set; }
    public int Age { get; set; }
    public string Gender { get; set; }
    public long TimeStamp { get; set; }
}
    
public class Student
{
    public Guid Id { get; set; }
    public string Name { get; set; }
    public int Age { get; set; }
    public long TimeStamp { get; set; }
}
    
public class Person<br>
{
    public string Name { get; set; }
    public int Age { get; set; }
}

我创建4个列表:

var studentList = new List<Student>();// fill the List with a lot of Stundents
var employeeList = new List<Student>(); // fill the List with a lot of employees
var personList1 = new List<Person>();
var personList2 = new List<Person>();

选择所有学生和员工

var allStudents = studentList.Select(a => a); // does not make a lot of sence but for testing 
var allEmployee = employeeList.Select(b => b);

我想将所有学生映射到

personList1.AddRange(allStudents.Select(a => new Person()
            {
               Age = a.Age,
               Name = a.Name
            } ));

我想让所有在 allStundent 列表中未提及 TimeStape 值的员工

var allEmployeesWithDifferentTimeStampThanStundent =
    allEmployee.Where(a => !allStudents.Select(b =>b.TimeStamp).Contains(a.TimeStamp));

再次映射

personList2.AddRange(allEmployeesWithDifferentTimeStampThanStundent.Select
(a => new Person()
    {
    Age = a.Age,
    Name = a.Name
    } ));

合并两个列表

personList1.AddRange(personList2);

有没有更好、更有效的方法可以做到这一点?

personList2 变量似乎只是作为投影到Person类型的中间体而存在——如果是这种情况,你可以跳过它的创建并使用查询语法,如下所示:

var personsFromNonMatchingEmployees =
    from employee in allEmployee
    join student in allStudents
    on employee.TimeStamp equals student.TimeStamp into studentsWithMatchingTimeStamp
    where !studentsWithMatchingTimeStamp.Any()
    select new Person { Age = employee.Age, Name = employee.Name };
personList1.AddRange(personsFromNonMatchingEmployees);

这类似于其他 GroupJoin 方法,因为编译器将上述内容转换为 GroupJoin 调用。使用加入/组联接必然比Where..Contains方法表现更好,因为它利用了哈希 - 换句话说,这是一个算法上的 Big-O 改进,对于任何超过几个学生或员工实例都应该非常明显。

通过在查询中选择new Person对象,我可以完全绕过personList2列表。我发现我几乎总是能够通过像这样选择来消除临时列表,该选择投影到我真正感兴趣的类型。我还省略了new Person { .. }上的(),因为编译器不需要它。

羞于改变遗产并使员工:人和学生:人,我认为没有更多需要改进的地方。

您可以使用

GroupJoin查找没有具有相同时间戳的匹配Student记录的所有员工:

var employeesDiffTS = allEmployee
    .GroupJoin(allStudents, e => e.TimeStamp, s => s.TimeStamp, (e, students) => new { Emp = e, HasMatch = students.Any() })
    .Where(em => !em.HasMatch)
    .Select(em => em.Emp)
personList2.AddRange(employeeDiffTS.Select(a => new Person { Age = a.Age, Name = a.Name }));
personList1.AddRange(personList2);

相关内容

  • 没有找到相关文章

最新更新