2012-02-02 13 views
0

2つのインメモリコレクションをLINQ-to-Objectsとマージする最も効率的な方法を見つけるのに役立つ必要があります。私の場合は、プロパティ値に基づいて特定のアイテムを除外する必要があるため、単純な結合または連結ではありません。2つのコレクションを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 
{ 
    ... 
} 

注、従業員もお客様のかもしれません。また、ではありません

  1. も従業員
  2. ないすべてのお客様のすべての従業員を:

    私は従業員のリストと顧客のリストを持っており、これらの規則に従って、すべての人のリストを生成したいです顧客と終端されていません(TerminationDate == null)の

  3. 顧客と従業員の両方であるAND(TerminationDate == null)を終了していないすべての人

Whをこれを達成する最も効率的な方法は?

+1

顧客は、とにかく従業員することはできません。 「**同じ名前の顧客**を従業員として除外する」という意味ですか? –

+0

従業員と顧客の両方が同時に継承することができるのは明らかに、オブジェクトをモデル化する最も適切な方法ではないかもしれません。この場合、私は相続よりも組成が好きです。 –

+0

はい、従業員も顧客である可能性があると言ったとき、私は現実世界ではなくオブジェクトを意味しました。混乱させて申し訳ありません。 – SonOfPirate

答えて

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; 
    } 
} 
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); 
関連する問題