2009-11-12 19 views
5

これは.NET 2.0を使用して、C#で記述されています。類似のプロパティを持つ2つの異なるオブジェクトを比較する方法

私は2つのオブジェクトのリストを持っています。それらは関連するオブジェクトではありませんが、GUIDベースの一意の識別子など、比較できる共通のものは です。これらの2つのリストには、 というフィルタが、最初の2つのリストに含まれているIDの と一致する場合と一致しない場合があります。

各オブジェクトリストを「オブジェクト」にキャストし、 でソートすることを考えましたが、一度キャストされるとIDプロパティにアクセスできるとは思えません。 m 2つのリストを並べ替える方法は、並べ替えるリストが何であるかを知るのにやや愚かでなければならないと考えています。

個々のオブジェクトリストを持ち込んで、IDだけのリストに対してソートできるようにするにはどうすればよいでしょうか?

+0

ソートまたはフィルタリング?何で並べ替える? – dtb

+0

実際にフィルタリングしています。 object.GuidId == list.GuidIdはオブジェクトを返します。 – Chris

答えて

15

異なるオブジェクトのそれぞれに共通のインターフェイスを実装する必要があります。次に、そのインタフェース用のIComparer < T>を作成し、それをあなたのソートで使用します。

+3

共通のインターフェイスを実装できる場合(オブジェクトのいずれかまたは両方を所有していないため)、共通インターフェイスを実装するアダプタクラスを作成する必要があります。それからあなたは金色です。 – plinth

+0

つまり、基本的には、各オブジェクトを両方の共通要素を含むクラス(インタフェース)型にキャストして、結果の(同じ型の)オブジェクトを比較します。インターフェイスを使用すると、明示的なキャスト操作が回避されます。 –

+0

JimmyのAutoMapperのようなもので、関連するオブジェクト型のIComparerクラスを登録するのは面白いと思います。思考? –

0

私は、私は完全にあなたが望むものを理解していることはよく分からないが、あなたはリストから一致する項目を選択するだけでなく、それらをソートするためにLINQを使用することができます。あるリストの値が別のリストでフィルタリングされ、ソートされた単純な例を次に示します。

 List<int> itemList = new List<int>() { 9,6,3,4,5,2,7,8,1 }; 
     List<int> filterList = new List<int>() { 2, 6, 9 }; 

     IEnumerable<int> filtered = itemList.SelectMany(item => filterList.Where(filter => filter == item)).OrderBy(p => p); 
0

私はまだAutoMapperを使用する機会を持っていましたが、あなたはcheck it outしたい記述するものとされていません。ジミー・ボガードのポストから:

AutoMapper規則

AutoMapperが平坦化するので、それは を探します:プロパティ名

ネストされたプロパティ名(商品名にProduct.Name マップを、マッチング

を)ワットを開始

方法を PascalCaseの命名規則を想定して単語i番目、 のでGetTotalは()

あなたはすべての 「ドット」と「取得」を削除した場合、既に は、基本的に

を設定した既存の型マップ、AutoMapper意志 試合をトータルにマッピング「ゲット」プロパティ名。今、 AutoMapperは不一致 タイプに失敗しますが、いくつかの他の理由ではありません。

0

私はあなたの最終結果として望むものは全くわからない、しかし....

次の2つの異なる種類のプロパティを比較している場合は、2つの辞書にプロパティ名と対応する値を予測でき。そして、その情報を使って、ある種の並べ替え/プロパティ値の違いを行います。

 Guid newGuid = Guid.NewGuid(); 
     var classA = new ClassA{Id = newGuid}; 
     var classB = new ClassB{Id = newGuid}; 

     PropertyInfo[] classAProperties = classA.GetType().GetProperties(); 

     Dictionary<string, object> classAPropertyValue = classAProperties.ToDictionary(pName => pName.Name, 
                       pValue => 
                       pValue.GetValue(classA, null)); 

     PropertyInfo[] classBProperties = classB.GetType().GetProperties(); 
     Dictionary<string, object> classBPropetyValue = classBProperties.ToDictionary(pName => pName.Name, 
                       pValue => 
                       pValue.GetValue(classB, null)); 


internal class ClassB 
{ 
    public Guid Id { get; set; } 
} 

internal class ClassA 
{ 
    public Guid Id { get; set; } 
} 

classAPropertyValue 
Count = 1 
    [0]: {[Id, d0093d33-a59b-4537-bde9-67db324cf7f6]} 

classBPropetyValue 
Count = 1 
    [0]: {[Id, d0093d33-a59b-4537-bde9-67db324cf7f6]} 
1

.NET 2のみを使用します。0方法:あなたのクラスは、共通のインタフェースを実装していない場合は

class Foo 
{ 
    public Guid Guid { get; } 
} 

List<Foo> GetFooSubset(List<Foo> foos, List<Guid> guids) 
{ 
    return foos.FindAll(foo => guids.Contains(foo.Guid)); 
} 

、あなたは個別タイプごとにGetFooSubsetを実装する必要があります。

+0

.NET 2.0はラムダ式をサポートしておらず、またSystem.Linqによって拡張メソッドが追加されていません。あなたの例には少なくとも.NET 3.0が必要です。 –

+1

@Karim:FindAllはLINQによって追加された拡張メソッドではなく、バージョン2.0以降の.NETフレームワークの一部である 'List 'クラスによって提供される通常のメソッドです。ラムダ式にはC#3.0コンパイラが必要ですが、必ずしも.NET 3.0である必要はありません。 – dtb

0

Thistは基本的に何をしたいあなたを取得する必要があります - しかし、あなたはそこにインターフェイスを追加するだけで、あなたのオリジナルのクラスを変更するアクセス権を持っている場合は、

class T1 
{ 
    public T1(Guid g, string n) { Guid = g; MyName = n; } 
    public Guid Guid { get; set; } 
    public string MyName { get; set; } 
} 
class T2 
{ 
    public T2(Guid g, string n) { ID = g; Name = n; } 
    public Guid ID { get; set; } 
    public string Name { get; set; } 
} 
class Test 
{ 
    public void Run() 
    { 
     Guid G1 = Guid.NewGuid(); 
     Guid G2 = Guid.NewGuid(); 
     Guid G3 = Guid.NewGuid(); 
     List<T1> t1s = new List<T1>() { 
      new T1(G1, "one"), 
      new T1(G2, "two"), 
      new T1(G3, "three") 
     }; 
     List<Guid> filter = new List<Guid>() { G2, G3}; 

     List<T1> filteredValues1 = t1s.FindAll(delegate(T1 item) 
     { 
      return filter.Contains(item.Guid); 
     }); 

     List<T1> filteredValues2 = t1s.FindAll(o1 => filter.Contains(o1.Guid)); 
    } 
} 
+0

私はそこに過度の過労を覚えました。 – dice

2

オーケーLINQを使用する方がよい場合が、マシューは、それがスポットでしたに。私はここに少し夢中になり、2.0の匿名の代理人を使って完全なソリューションを定義しました。 (私は3.0ラムダにはまっていると思います;そうでなければ、もし私が2005年をまだ使っていたら、foreachループでこれを書いたでしょう)。

基本的に共通のプロパティを持つインターフェイスを作成します。 yoruを2つのクラスがインターフェイスを実装するようにします。インタフェースとしてキャストされた共通リストを作成し、その値を新しいリストにキャストしてリッピングします。一致しない項目はすべて削除します。

//Program Output: 
List1: 
206aa77c-8259-428b-a4a0-0e005d8b016c 
64f71cc9-596d-4cb8-9eb3-35da3b96f583 

List2: 
10382452-a7fe-4307-ae4c-41580dc69146 
97f3f3f6-6e64-4109-9737-cb72280bc112 
64f71cc9-596d-4cb8-9eb3-35da3b96f583 

Matches: 
64f71cc9-596d-4cb8-9eb3-35da3b96f583 
Press any key to continue . . . 


using System; 
using System.Collections.Generic; 
using System.Text; 

namespace ConsoleApplication8 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      //test initialization 
      List<ClassTypeA> list1 = new List<ClassTypeA>(); 
      List<ClassTypeB> list2 = new List<ClassTypeB>(); 

      ClassTypeA citem = new ClassTypeA(); 
      ClassTypeB citem2 = new ClassTypeB(); 
      citem2.ID = citem.ID; 

      list1.Add(new ClassTypeA()); 
      list1.Add(citem); 
      list2.Add(new ClassTypeB()); 
      list2.Add(new ClassTypeB()); 
      list2.Add(citem2); 


      //new common list. 
      List<ICommonTypeMakeUpYourOwnName> common_list = 
         new List<ICommonTypeMakeUpYourOwnName>(); 

      //in english, give me everything in list 1 
      //and cast it to the interface 
      common_list.AddRange(
       list1.ConvertAll<ICommonTypeMakeUpYourOwnName>(delegate(
        ClassTypeA x) { return (ICommonTypeMakeUpYourOwnName)x; })); 

      //in english, give me all the items in the 
      //common list that don't exist in list2 and remove them. 
      common_list.RemoveAll(delegate(ICommonTypeMakeUpYourOwnName x) 
       { return list2.Find(delegate(ClassTypeB y) 
         {return y.ID == x.ID;}) == null; }); 

      //show list1 
      Console.WriteLine("List1:"); 
      foreach (ClassTypeA item in list1) 
      { 
       Console.WriteLine(item.ID); 
      } 
      //show list2 
      Console.WriteLine("\nList2:"); 
      foreach (ClassTypeB item in list2) 
      { 
       Console.WriteLine(item.ID); 
      } 

      //show the common items 
      Console.WriteLine("\nMatches:"); 
      foreach (ICommonTypeMakeUpYourOwnName item in common_list) 
      { 
       Console.WriteLine(item.ID); 
      } 
     } 

    } 

    interface ICommonTypeMakeUpYourOwnName 
    { 
     Guid ID { get; set; } 
    } 

    class ClassTypeA : ICommonTypeMakeUpYourOwnName 
    { 
     Guid _ID; 
     public Guid ID {get { return _ID; } set { _ID = value;}} 
     int _Stuff1; 
     public int Stuff1 {get { return _Stuff1; } set { _Stuff1 = value;}} 
     string _Stuff2; 
     public string Stuff2 {get { return _Stuff2; } set { _Stuff2 = value;}} 

     public ClassTypeA() 
     { 
      this.ID = Guid.NewGuid(); 
     } 
    } 

    class ClassTypeB : ICommonTypeMakeUpYourOwnName 
    { 
     Guid _ID; 
     public Guid ID {get { return _ID; } set { _ID = value;}} 
     int _Stuff3; 
     public int Stuff3 {get { return _Stuff3; } set { _Stuff3 = value;}} 
     string _Stuff4; 
     public string Stuff4 {get { return _Stuff4; } set { _Stuff4 = value;}} 

     public ClassTypeB() 
     { 
      this.ID = Guid.NewGuid(); 
     } 

    } 
} 
+0

FYI ... OPは2.0と言った。私は2005 VSと仮定しているので、3.0 VS 2008のショートカットはありません。 – Nathan

+0

これはかなりうまくいく。あまりにも悪い私は2つの受け入れられた答えを出すことはできません。 – Chris

関連する問題