2011-10-19 8 views
0

私はList<CustomObject>を持っており、重複を削除したいと考えています。
2つのカスタムオブジェクトの値がproperty: Cityの場合、それらを重複して呼び出します。
私はIEquatableを次のように実装しましたが、リストから重複を取り除くことはできません。リストからの重複を避けるためにIEquatable <T>を実装する<T>

何が欠けていますか?

public class CustomAddress : IAddress, IEqualityComparer<IAddress> 
{ 
    //Other class members go here 

    //IEqualityComparer members 
    public bool Equals(IAddress x, IAddress y) 
    { 
     // Check whether the compared objects reference the same data. 
     if (ReferenceEquals(x, y)) return true; 

     // Check whether any of the compared objects is null. 
     if (ReferenceEquals(x, null) || ReferenceEquals(y, null)) 
      return false; 

     // Check whether the Objects' properties are equal. 
     return x.City.Equals(y.City); 

    } 

    public int GetHashCode(IAddress obj) 
    { 
     // Check whether the object is null. 
     if (ReferenceEquals(obj, null)) return 0; 

     int hashAreaName = City == null ? 0 : City.GetHashCode(); 
     return hashAreaName; 
    } 
} 

私はあなたが比較演算を必要とするだけで、特定のプロパティの重複を一致させるには、.NET 3.5

+1

LinqのDistinct()拡張メソッドを使用します。 –

答えて

1

を追加する前に、Containsメソッドを使用しているチェックすることを前提としIEquatable<CustomObject>なくIEquatable<IAddress>を実装している場合List<CustomObject>テストためですEqualsGetHashCodeを上書きする必要があります。既存のリストをフィルタリングする必要がある場合は、リストの名前空間System.Linqを通じてDistinct()を呼び出すだけです。

var noDupes = list.Distinct(); 

これにより、重複しないシーケンスが得られます。それを具体的なリストにする必要がある場合は、単に呼び出しの最後にToList()を追加してください。

var noDupes = list.Distinct().ToList(); 

もう1つの回答では、IEqualityComparer<CustomObject>を実装しています。 EqualsGetHashCodeを直接オーバーライドすることは不可能(ソースを制御しない)か、意味がない(この特定のケースでの等価性の考え方は、このクラスでは普遍的ではない)場合に便利です。この場合、比較者as demonstratedを定義し、比較者のインスタンスにDistinctのオーバーロードを指定します。

最後に、リストを構築して重複を避けたい場合は、前述のhereのようにHashSet<T>を使用できます。 HashSetは、コンストラクタ内のカスタム比較関数も受け入れます。そのため、オプションでそれを含めることもできます。 .NETライブラリのメソッドを使用していないが、ピンチに有用であることができ

var mySet = new HashSet<CustomObject>(); 
bool isAdded = mySet.Add(myElement); 
// isAdded will be false if myElement already exists in set, and 
// myElement would not be added a second time. 
// or you could use 
if (!mySet.Contains(myElement)) 
    mySet.Add(myElement); 

もう一つのオプションでは、大まかな実装hereを見ることができますジョンスキートのDistinctBy、です。あなたはFunc<MyObject, Key>ラムダ式を直接提出し、EqualsGetHashCode(またはカスタム比較者)のオーバーライドを完全に省略します。

var noDupes = list.DistinctBy(obj => obj.City); // NOT part of BCL 
0

を使用しています。

class MyComparer : IEqualityComparer<CustomObject> 
{ 
    public bool Equals(CustomObject x, CustomObject y) 
    { 
     return x.City.Equals(y.City); 
    } 

    public int GetHashCode(CustomObject x) 
    { 
     return x.City.GetHashCode() 
    } 
} 

使用法:

var yourDistictObjects = youObjects.Distinct(new MyComparer()); 

編集:は何が必要ありません。このスレッドを発見し、私は過去にそれに言及思う:

Remove duplicates in the list using linq

一つの答え興味深いと思っていたのですが(それはどうしたのですか)、

var distinctItems = items.GroupBy(x => x.Id).Select(y => y.First()); 

あなたが必要とするものを実行するが、他の方法ほど効率的でないかもしれない1つのライナーです。

+0

これはやや誤解を招きますが、ユーザーはcomparerを必要とせず、EqualsとGetHashCodeをオーバーライドしました。しかし、それは答えを無効にしません。ユーザーが行ったように、外部比較演算子とEqualsおよびGetHashCodeをオーバーライドするのはいつですか? –

+0

@Anthony Pegram良い質問:)私は別のプロジェクトでそれをやっていた方法を見て、それをカットアンドペーストしました...今、あなたは私がそのように笑っていない理由を考えています。それはしかし、動作します。 – Kelsey

+0

私のCustomAddressクラスがIEqualityComparer を実装していて、別のComparerクラスを宣言する必要があるのはなぜですか? – iniki

0

ちょうど.Equals(正しく実装しています)を実装することで、重複が防止されないようにして、List<T>に追加しました。実際に手動で削除する必要があります。

List<CustomObject>の代わりにHashSet<CustomObject>を使用してください。重複を含むことはありません。

0

あなたは

をしたとして、あなたのクラス(CustomObjectが)私は重複のためにあなたがして、新しいメンバー

関連する問題