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