0

私は次のような人のクラスを持っています:

Public Class Person
{
public int Id {get; set;}
public int FirstName {get; set;}
public int LastName {get; set;}
}

Person オブジェクトのリストを作成します。

List<Person> AllPersons = GetAllPersons();

GetAllPersons() には、ID に基づいて一意で繰り返しのない人物オブジェクトを提供するこのコードがあります。

        return this.colLoadExternalData.GroupBy(p => p, new MyClass()).Where(g => g.Count() == 1).Select(g => g.Single()).ToList();

つまり、ソースに Id = 123 の人物が 2 人いた場合、123 はリストに表示されません。

IEqualityComparer を実装するクラスは次のとおりです。

public class MyClass : IEqualityComparer<Person>
{
    public bool Equals(Person x, Person y)
    {
        return x.Id == y.Id;
    }

    public int GetHashCode(Person obj)
    {
        return obj.Id.GetHashCode();
    }
}  

MyClass セットは、ID に基づく ID です。

そのプロパティ値に基づいて一意の人物を識別する FirstName や LastName などの人物クラスの ID プロパティを設定する規定がある外部構成ファイルがあります。

したがって、構成ファイルにキーとして「FirstName」と記載されている場合、MyClass は次のようになります。

public class MyClass : IEqualityComparer<Person>
{
    public bool Equals(Person x, Person y)
    {
        return x.FirstName == y.FirstName;
    }

    public int GetHashCode(Person obj)
    {
        return obj.FirstName.GetHashCode();
    }
} 

人物オブジェクトを追加する前に実際に辞書を使用していましたが、ソースに ID 123 の 2 人の人物のような繰り返しエントリがある場合は、1 つの人物オブジェクトが追加されます。外部ソースからの繰り返しレコードを含めないでください。

私ができることは、重複のリストを別のリストに維持することです。そのリストで単純な foreach を実行し、次のように辞書から人物オブジェクトを削除します。

foreach(var dup in Duplicates)
{
  UniquePersonObjects.Remove(dup);
}

ここでは IEqualityComparer は使用されていません。外部ソースから辞書にレコードを追加し、重複リストに基づいてその辞書をさらにフィルター処理するだけです。

これを行うより良い方法はありますか?

よろしく。

4

2 に答える 2

1

これまでに見つけた最良の実装は、次のリンクで見つけることができます

public class EqualityComparer:IEqualityComparer { private Func equalsFunction; private Func getHashCodeFunction;

public EqualityComparer(Func<T, T, bool> equalsFunction)
{
    this.equalsFunction = equalsFunction;
}

public EqualityComparer(Func<T, T, bool> equalsFunction, 
    Func<T, int> getHashCodeFunction) : this(equalsFunction)
{
    this.getHashCodeFunction = getHashCodeFunction;
}

public bool Equals(T a, T b)
{
    return equalsFunction(a, b);
}

public int GetHashCode(T obj)
{
    if (getHashCodeFunction == null)
        return obj.GetHashCode();
    return getHashCodeFunction(obj);
}

}

これで、フィルタリング用の独自のメソッドを作成できます。たとえば、次のようになります。

EqualityComparer equalityComparer = new EqualityComparer((s1, s2) => s1.Id == s2.Id);

于 2014-04-15T07:37:52.017 に答える
0

の構成を使用してMyClass、さまざまなチェックを処理できます。

public class MyClass : IEqualityComparer<Person>
{
    // here you set the configuration
    private PersonCompareConfiguration personCompareConfiguration;

    public bool Equals(Person x, Person y)
    {
        switch(personCompareConfiguration)
        {
            case CompareId:
                return x.Id == y.Id;
                break;
            case CompareFirstname:
                return x.FirstName == y.FirstName;
                break;
        }
        throw new InvalidArgumentException("personCompareConfiguration cannot be handled");
    }

    public int GetHashCode(Person obj)
    {
        switch(personCompareConfiguration)
        {
            case CompareId:
                return obj.Id.GetHashCode();
                break;
            case CompareFirstname:
                return obj.FirstName.GetHashCode();
                break;
        }
        throw new InvalidArgumentException("personCompareConfiguration cannot be handled");
    }
}

public enum PersonCompareConfiguration
{
    CompareId,
    CompareFirstname
}

もう1つの(よりスマートな)方法は、MEFを使用しての実装をエクスポートすることですIEqualityComparer<Person>。汎用インターフェースをエクスポートおよびインポートする方法を説明するこの回答をご覧ください。

于 2013-03-04T09:29:49.600 に答える