2016-09-12 7 views
1

私はArrayListの2つの配列を持っています。C#:カスタムクラスの2つのArrayListを比較し、重複を見つける

public class ProductDetails 
{ 
    public string id; 
    public string description; 
    public float rate; 
} 

ArrayList products1 = new ArrayList(); 
ArrayList products2 = new ArrayList(); 
ArrayList duplicateProducts = new ArrayList(); 

は今、何をしたいすべての製品(ProductDetailsクラスのすべてのフィールドとは)products1products2の両方に重複した説明を持つことです。

Iは、従来の方法のような2つのために/ whileループを実行することができ、私はに両方のアレイを10Kを超える要素を有するであろう場合には、特に非常に遅いであろう。

おそらく何かがLINQで実行できます。

+2

'List 'を使用し、 'ArrayList'では使用しません。 – SLaks

+2

おそらくデータベースを使うべきです。 – SLaks

+2

私は@SLaksに同意します。これは、Outter SelectでSubQueryを使用する方がはるかに簡単です。Select Distinctを選択し、Count with Count(*)> = 2を使用してグループを内部で選択します。 – MethodMan

答えて

1

あなたはLINQのを使用したい場合、あなたはGetHashCodeメソッドを(等しい両方のメソッドをオーバーライドし、独自のEqualityComparerを書く必要があります)今

public class ProductDetails 
    { 
     public string id {get; set;} 
     public string description {get; set;} 
     public float rate {get; set;} 
    } 

public class ProductComparer : IEqualityComparer<ProductDetails> 
{ 

    public bool Equals(ProductDetails x, ProductDetails y) 
    { 
     //Check whether the objects are the same object. 
     if (Object.ReferenceEquals(x, y)) return true; 

     //Check whether the products' properties are equal. 
     return x != null && y != null && x.id.Equals(y.id) && x.description.Equals(y.description); 
    } 

    public int GetHashCode(ProductDetails obj) 
    { 
     //Get hash code for the description field if it is not null. 
     int hashProductDesc = obj.description == null ? 0 : obj.description.GetHashCode(); 

     //Get hash code for the idfield. 
     int hashProductId = obj.id.GetHashCode(); 

     //Calculate the hash code for the product. 
     return hashProductDesc^hashProductId ; 
    } 
} 

、あなたはこのオブジェクトを持っていると仮定:

ProductDetails [] items1= { new ProductDetails { description= "aa", id= 9, rating=2.0f }, 
         new ProductDetails { description= "b", id= 4, rating=2.0f} }; 

ProductDetails [] items= { new ProductDetails { description= "aa", id= 9, rating=1.0f }, 
         new ProductDetails { description= "c", id= 12, rating=2.0f } }; 


IEnumerable<ProductDetails> duplicates = 
    items1.Intersect(items2, new ProductComparer()); 
+0

コメントありがとうございました。私は確かにこのコードを試しますが、本当に私は 'GetHashCode'ものについては取得していません。カスタムクラスに複数のフィールドがある場合はどうなりますか?同じパターンで '^'する必要がありますか? 'hasProductDesc^hasProductId^hasProductRate^hasProductMake'のように?また、記述に基づいてこれら2つの異なるオブジェクト/ arraylistを比較したい場合は、他のフィールドが異なる可能性があることを意味します。 –

+0

こんにちは、複数のプロパティがある場合は、最終的に多くのプロパティをXORすると最終的に0に収束し、多くの衝突を引き起こす可能性があるので、私はそれをしません。したがって、Equalsメソッドを破棄します。詳細はこちらをお読みください。 [汎用配列を含むオブジェクトのGetHashCodeオーバーライド](http://stackoverflow.com/questions/638761/gethashcode-override-of-object-containing-generic-array/639098#639098) – raven

+0

上記のコードでは、等価はidとdescriptionで定義されます。説明だけであれば、この 'x.id.Equals(y.id)'とこの '^ hashProductId'を削除することができ、うまく動作するはずです。 – raven

0

System.Object.Equalsメソッドをオーバーライドすることを検討してください。それが提案されている

すると、この実装は最適ではないと考えてください。..

Moreover-:

var result = products1.Where(product=>products2.Contains(product)); 

EDIT:

public class ProductDetails 
    { 
    public string id; 
    public string description; 
    public float rate; 

    public override bool Equals(object obj) 
    { 
     if(obj is ProductDetails == null) 
      return false; 

     if(ReferenceEquals(obj,this)) 
      return true; 

     ProductDetails p = (ProductDetails)obj; 
     return description == p.description; 
    } 
    } 

フィルタリングは、その後のような単純なものでしょうあなたがデータベースを使用していることをあなたの質問にコメントしてください。
このようにパフォーマンスは最適化されます - データベース実装ごとに
いずれの場合でも、オーバーヘッドはあなたのものではありません。 System.Object.GetHashCode方法
過負荷:

ただし、辞書やHashSetのを使用してこのコードを最適化することができます

var hashSet = new HashSet<ProductDetails>(products1); 
var result = products2.Where(product=>hashSet.Contains(product)); 

public override int GetHashCode() 
{ 
    return description.GetHashCode(); 
} 

あなたは今、これを行うことができます

ルックアップのコストが低くなるため、パフォーマンスがある程度向上します。

+1

また、 'GetHashCode()'をオーバーライドする必要があります。 – SLaks

+0

これは 'O(n^2)'です。辞書を使う。 – SLaks

+0

@SLaks申し訳ありませんが、この時は怠惰です。まもなく追加されます。 –

-1

10k要素は何もありませんが、適切なコレクションタイプを使用してください。 ArrayListは長く非難されます。List<ProductDetails>を使用してください。

次のステップでは、クラスに適切なEqualsGetHashCodeのオーバーライドを実装しています。

public class ProductDetails 
{ 
    public string id; 
    public string description; 
    public float rate; 

    public override bool Equals(object obj) 
    { 
     var p = obj as ProductDetails; 
     return ReferenceEquals(p, null) ? false : description == obj.description; 
    } 

    public override int GetHashCode() => description.GetHashCode();  
} 

は、今は選択肢があります。ここでの仮定は、それはあなたがビューの重複ポイントから気に何以来descriptionがキーであるということです。これはあなたに線形(O(n))時間複雑さを与えます

​​

、最高のあなたが得ることができます。これを行う1つの簡単で効率的な方法は、ハッシュセットを使用しています。

関連する問題