3

我有这 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
            } ));

我想获取 allStudent 列表中未提及 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);

有没有更好更有效的方法来做到这一点?

4

2 回答 2

4

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 调用。join/group-join 的使用必然比该Where..Contains方法执行得更好,因为它使用了散列 - 换句话说,它是一种算法 Big-O 改进,对于几个 Student 或 Employee 实例来说应该是非常明显的。

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

羞于改变继承并使员工:个人和学生:个人,我认为没有太多需要改进的地方。

于 2013-01-29T03:39:58.857 回答
2

您可以使用它来查找没有具有相同时间戳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);
于 2013-01-28T22:26:26.527 回答