2017-01-05 3 views
3

Ich versuche, eine IEqualityComparer zu implementieren, die eine Toleranz für einen Datumsvergleich aufweist. Ich habe auch in this question geschaut. Das Problem ist, dass ich eine Problemumgehung nicht verwenden kann, da ich die IEqualityComparer in einem LINQ .GroupJoin() verwende. Ich habe ein paar Implementierungen ausprobiert, die Toleranz zulassen. Ich kann die Equals() zu arbeiten, weil ich beide Objekte habe, aber ich kann nicht herausfinden, wie Sie GetHashCode() implementieren.Verwenden von IEqualityComparer GetHashCode mit einer Toleranz

Mein bester Versuch sieht ungefähr so ​​aus:

public class ThingWithDateComparer : IEqualityComparer<IThingWithDate> 
{ 
    private readonly int _daysToAdd; 

    public ThingWithDateComparer(int daysToAdd) 
    { 
     _daysToAdd = daysToAdd; 
    } 

    public int GetHashCode(IThingWithDate obj) 
    { 
     unchecked 
     { 
      var hash = 17; 
      hash = hash * 23 + obj.BirthDate.AddDays(_daysToAdd).GetHashCode(); 
      return hash; 
     } 
    } 

    public bool Equals(IThingWithDate x, IThingWithDate y) 
    { 
     throw new NotImplementedException(); 
    } 
} 

public interface IThingWithDate 
{ 
    DateTime BirthDate { get; set; } 
} 

Mit .GroupJoin() ein HashTable aus dem GetHashCode() Gebäude es die Tage gilt für beide/alle Objekte hinzuzufügen. Dies funktioniert nicht.

+0

Ist daysTo die Toleranz, wie in Jan 5 entspricht Jan 6 innerhalb einer Toleranz von 1 Tag? Diese Definition von Gleichheit ist nicht transitiv, also bezweifle ich, dass es möglich ist, IEqualityComparer außerhalb der trivialen Lösung des Zurückgebens des gleichen Hash-Codes für jedes Objekt korrekt zu implementieren. –

+0

Vergiss es. Ersetzen Sie die 'GroupJoin' durch' SelectMany' und einfache 'Where' (nicht sehr performant, sollte aber funktionieren). –

+0

@mikez Ja, das ist die Toleranz. Die Benennung ist einfach schlecht. Wenn ich das nicht schaffen kann, werde ich einfach eine benutzerdefinierte Version von 'GroupJoin()' implementieren. –

Antwort

2

Das Problem ist konzeptionell unmöglich. Sie versuchen, Objekte auf eine Weise zu vergleichen, die keine Gleichheitsform aufweist, die für die Vorgänge erforderlich ist, die Sie damit ausführen möchten. Zum Beispiel ist GroupJoin von der Annahme abhängig, dass, wenn A gleich B ist und B gleich C ist, dann ist A gleich C, aber in Ihrer Situation ist das nicht wahr. A und B können "nahe genug" zusammen sein, damit Sie sie gruppieren können, aber A und C sind möglicherweise nicht.

Sie müssen IEqualityComparer überhaupt nicht implementieren, weil Sie den Vertrag, den es erfordert, nicht erfüllen können. Wenn Sie eine Zuordnung von Elementen in einer Sammlung zu allen Elementen in einer anderen Sammlung erstellen möchten, die "nah genug" sind, müssen Sie diesen Algorithmus selbst schreiben (dies ist sehr wahrscheinlich schwierig, aber das ineffizient zu tun ist nicht, sollte nicht so schwierig sein, anstatt GroupJoin zu verwenden, weil es nicht in der Lage ist, diese Operation durchzuführen.

+0

Dies scheint die richtige Antwort zu sein. Es ist enttäuschend, dass die Antwort lautet, dass es keine Antwort gibt. –

1

Ich kann keine Möglichkeit sehen, einen logischen Hash-Code für Ihre gegebenen Kriterien zu generieren.
Der Hash-Code wird verwendet, um festzustellen, ob 2 Daten zusammenhalten sollten. Wenn sie zusammen gruppieren sollten, müssen sie denselben Hash-Code zurückgeben.

Wenn Ihr "Float" 5 Tage beträgt, bedeutet dies, dass 1/1/2000 den gleichen Hash-Code wie 1/4/2000 generieren muss und 1/4/2000 den gleichen Hashcode wie 1/8/2000 (da sie beide innerhalb von 5 Tagen voneinander sind). Das bedeutet, dass 1/1/2000 den gleichen Code wie 1/8/2000 hat (denn wenn a = b und b = c, a = c).

1/1/2000 und 1/8/2000 sind außerhalb der 5 Tage "float".

+0

Sehr wahr. Ich denke, dass ich die Verwendung von 'GroupJoin' verschrotten und eine Version implementieren muss, die einen' Comparer' mit einem Seed von der linken Seite erlaubt. –

Verwandte Themen