2013-05-11 8 views
5

私は2つのListsを持っています。 IDに基づいて一致した値と一致しない値を取得し、結果を別のListに追加したいとします。私はIntersect/Exceptを使ってこれらの両方を得ることができます。リスト<>を別のリスト<>にコピーする方法c#

しかし、結果の変数(一致および不一致)にはIDしか得られません。テンプレートのすべてのプロパティが必要です。

List<Template> listForTemplate = new List<Template>(); 
List<Template1> listForTemplate1 = new List<Template1>(); 

var matches = listForTemplate .Select(f => f.ID) 
         .Intersect(listForTemplate1 .Select(b => b.ID)); 

var ummatches = listForTemplate .Select(f => f.ID) 
        .Except(listForTemplate1.Select(b => b.ID)); 

    public class Template 
    { 
     public string ID{ get; set; } 
     public string Name{ get; set; } 
     public string Age{ get; set; } 
     public string Place{ get; set; } 
     public string City{ get; set; } 
     public string State{ get; set; } 
     public string Country{ get; set; } 
    } 
    public class Template1 
    { 
     public string ID{ get; set; } 
    } 

答えて

3

あなたはこの単純なタスクのためIEqualityを実装したくない場合は、あなたは自分のLINQクエリを変更することができます。

var matches = listForTemplate.Where(f => listForTemplate1.Any(b => b.ID == f.ID)); 

var unmatches = listForTemplate.Where(f => listForTemplate1.All(b => b.ID != f.ID)); 

あなたがアクセスする前にnullをチェックすることをお勧めしますIDでも動作するはずです。

var matches = from item in listForTemplate 
       join id in listForTemplate1 on item.ID equals id.ID 
       select item; 

var unmatches = listForTemplate.Where(item => matches.All(elem => elem.ID != item.ID)); 

matchesunmatchesは両方必要なタイプがあるIEnumerable<Template>を次のようになります。比較のために

+0

私は一致と不一致のIDフィールド(すべてではない)のみを取得しています 私はすべてのプロパティが必要です。助けてください! –

+0

すべてのプロパティと比較する場合は、 'IEqualityComparer ' – Ric

+0

を実装する必要があります。すべてのプロパティと比較しません。 1つのプロパティ(ID)と比較し、別のリストのすべてのプロパティを取得する –

2

2番目のパラメータIEqualityComparerを使用して、オーバーロードされた関数を探しています。だからあなたの比較者(例:http://www.blackwasp.co.uk/IEqualityComparer.aspx)を作成し、交差/例外で同じ比較者を使用してください。

一般的な部分:おそらく、テンプレート用の共通インターフェースを持つ必要があります。クラスに文字列IDプロパティがあることを示すObjectWithIDあるいは、単にcomparerでdynamicを使用してください(しかし、これは非常に反パターンであると思います。悪い型を使用すると実行時エラーが発生する可能性があるためです)。

また、2つの異なるタイプの2つのコレクションを交差させると、Object(共通の親クラス)のコレクションになります。それからあなたはたくさんのキャスト(反パターン)しなければなりません。私はあなたのテンプレートクラスのための共通の抽象クラス/インターフェイスを作ることをお勧めし、それは動作しています。あなたが戻って要素をキャストする必要がある場合は、キャストが、visitiorパターンを使用しないでください:http://en.wikipedia.org/wiki/Visitor_pattern

例(良い):

static void Main(string[] args) 
    { 
     // http://stackoverflow.com/questions/16496998/how-to-copy-a-list-to-another-list-with-comparsion-in-c-sharp 

     List<Template> listForTemplate = new Template[] { 
      new Template(){ID = "1"}, 
      new Template(){ID = "2"}, 
      new Template(){ID = "3"}, 
      new Template(){ID = "4"}, 
      new Template(){ID = "5"}, 
      new Template(){ID = "6"}, 
     }.ToList(); 

     List<Template1> listForTemplate1 = new Template1[] { 
      new Template1(){ID = "1"}, 
      new Template1(){ID = "3"}, 
      new Template1(){ID = "5"} 
     }.ToList(); 

     var comp = new ObjectWithIDComparer(); 

     var matches = listForTemplate.Intersect(listForTemplate1, comp); 
     var ummatches = listForTemplate.Except(listForTemplate1, comp); 

     Console.WriteLine("Matches:"); 
     foreach (var item in matches) // note that item is instance of ObjectWithID 
     { 
      Console.WriteLine("{0}", item.ID); 
     } 
     Console.WriteLine(); 

     Console.WriteLine("Ummatches:"); 
     foreach (var item in ummatches) // note that item is instance of ObjectWithID 
     { 
      Console.WriteLine("{0}", item.ID); 
     } 
     Console.WriteLine(); 
    } 
} 

public class ObjectWithIDComparer : IEqualityComparer<ObjectWithID> 
{ 
    public bool Equals(ObjectWithID x, ObjectWithID y) 
    { 
     return x.ID == y.ID; 
    } 

    public int GetHashCode(ObjectWithID obj) 
    { 
     return obj.ID.GetHashCode(); 
    } 
} 

public interface ObjectWithID { 
    string ID { get; set; } 
} 

public class Template : ObjectWithID 
{ 
    public string ID { get; set; } 
    public string Name { get; set; } 
    public string Age { get; set; } 
    public string Place { get; set; } 
    public string City { get; set; } 
    public string State { get; set; } 
    public string Country { get; set; } 
} 
public class Template1 : ObjectWithID 
{ 
    public string ID { get; set; } 
} 

出力:前述のように

Matches: 
1 
3 
5 

Ummatches: 
2 
4 
6 

Press any key to continue . . . 
+0

いい例、特にインターフェイスと一緒に持ってきてください。 – Ric

0

、実装IEqualityComparer<T>インターフェイス。

IEqualityComparer<T> MSDN

その後Except()のためにあなたの方法では、引数としてこれを使用してIntersect()

Intersect

Intersect()方法のリンク上でこれを行う方法の良い例があります。

0

LINQを絶対に使用する必要がない場合は、このようなコードを作成しないでください。

var matches = new List<Template>(); 
    var unmatches = new List<Template>(); 

    foreach (var entry in listForTemplate) 
    { 
     bool matched = false; 
     foreach (var t1Entry in listForTemplate1) 
     { 
      if (entry.ID == t1Entry.ID) 
      { 
       matches.Add(entry); 
       matched = true; 
       break; 
      } 
     } 
     if (!matched) 
     { 
      unmatches.Add(entry); 
     } 
    } 

LINQのアプローチの欠点は、リストを2回トラバースしていることです。

1

、これも動作するはずですが(最初の部分は、@ MAVの答えのバリエーションです)。

しかし、MAVの答えはうまくいくので、私はそのために行くつもりです。

関連する問題