我有这三个班级:
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; }
}
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);
//我想让allStundent列表中没有提到TimeStape值的所有Employees
personList1.AddRange(allStudents.Select(a => new Person()
{
Age = a.Age,
Name = a.Name
} ));
//再次映射
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
} ));
有更好更有效的方法吗?
答案 0 :(得分: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改进,对于任何超过几个学生或者应该是非常明显的员工实例。
通过在查询中选择new Person
对象,我可以完全绕过personList2
列表。我发现我几乎总是能够通过做这样的选择来消除临时列表,这些选择投射到我真正感兴趣的类型。我也遗漏了()
上的new Person { .. }
,因为编译器不需要它。
羞于改变继承并使员工:人与人学生:伙计,我认为还有很多需要改进的地方。
答案 1 :(得分: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);