我需要帮助找到将两个内存中集合与LINQ-to-Objects合并的最有效方法。就我而言,它不是简单的连接或连接,因为某些项目需要根据属性值排除。
让我们使用以下示例(不太现实,但它说明了我需要的内容):
public abstract class Person
{
public String Name { get; set; }
}
public class Employee : Person
{
public DateTime? TerminationDate { get; set; }
}
public class Customer : Person
{
...
}
请注意,员工也可能是客户。
我有一份员工列表和一份客户列表,并希望按照这些规则生成所有人员的列表:
实现这一目标的最有效方法是什么?
答案 0 :(得分:0)
很难确定,但假设Jon猜测名称匹配是正确的,那么这是否具有概念意义?
请注意,它目前进行多次迭代,所以我通常在某些地方添加ToArray等,但我不想在尝试验证概念位时将其添加到此代码中。
var allPeople = ...;
var customers = allPeople.OfType<Customer>();
var employees = allPeople.OfType<Employee>();
var employeeNames = new HashSet(employees.Select(p => p.Name));
var customerNames = new HashSet(employees.Select(p => p.Name));
// list item #1
var customersNotEmployees = customers
.Where(c => employeeNames.Contains(c.Name) == false);
// will be used by #2 and #3
var employeesNotTerminated = employees
.Where(e => e.TerminationDate == null);
// list item #2
var employeesNotCustomersAndNotTerminated = employeesNotTerminated
.Where(e => customerNames.Contains(e.Name) == false);
// list item #3
var employeesAndCustomersAndNotTerminated = employeesNotTerminated
.Where(e => customerNames.Contains(e.Name) == true);
答案 1 :(得分:0)
虽然不一定是不正确的,詹姆斯的例子有点复杂,我希望并且不完整,因为我需要一个列表作为最终结果。
不确定这是最好的解决方案,但这是我到目前为止所提出的:
public abstract class Person
{
public String Name { get; set; }
public override Boolean Equals(Object other)
{
var otherPerson = other as Person;
if (otherPerson == null)
return false;
return Name.Equals(otherPerson.Name, StringComparison.OrdinalIgnoreCase);
}
}
public class Employee : Person
{
public DateTime? TerminationDate { get; set; }
}
public class Customer : Person
{
...
}
public class People
{
private IEnumerable<Customer> Customers;
private IEnumerable<Employee> Employees;
public IEnumerable<Person> GetCurrentPeople()
{
// Find all customers that are not employees
var onlyCustomers = Customers.Except(Employees);
// We only want employees that have not been terminated
var currentEmployees = Employees.Where(e => e.TerminationDate == null);
// Find all customers that are also employees
var customerAndEmployees = currentEmployees.Intersect(Customers);
// Now deal with employees that are not customers
var onlyEmployees = currentEmployees.Except(Customers);
// Join the lists together
var mergedRules = onlyCustomers.Concat(onlyEmployees).Concat(customerAndEmployees);
return mergedRules;
}
}