If I want to use objects of this class as keys in a Dictionary, what do I need to do? (10.0, 20.0) shouldn't exist as a key twice.
public class IntPoint
{
public Int64 X { get; set; }
public Int64 Y { get; set; }
public IntPoint(Int64 X, Int64 Y)
{
this.X = X; this.Y = Y;
}
public override int GetHashCode()
{
return X.GetHashCode() ^ Y.GetHashCode();
}
}
EDIT
public static Dictionary<IntPoint, List<int>> GetPolygonDuplicateIndixes(Polygon p)
{
Dictionary<IntPoint, List<int>> d = new Dictionary<IntPoint, List<int>>();
int i = 0;
foreach(IntPoint point in p)
{
if(!d.ContainsKey(point))
{
d[point] = new List<int>();
}
d[point].Add(i);
i++;
}
...
I'm getting duplicates in d. Why? 22002, 1501 occurs twice in p.
If you look at the Dictionary documentation, you'll see that if the keys implement
IEquatable, that equality implementation will be used instead.
The following link from MSDN recommends using combining X and Y using an XOR operation
http://msdn.microsoft.com/en-us/library/system.object.gethashcode.aspx#Y1500
public override int GetHashCode() {
return X ^ Y;
}
The thing to remember is that
It is important that the hash computation is fast
If two objects are equal then there hash mush be equal, but two objects with the same hash do not necessarily have to be equal
Your GetHashCode can look like:
public override int GetHashCode()
{
return X.GetHashCode() ^ Y.GetHashCode();
}
But you still need to override Equals and implement IEquatable interface.
You may also use Tuple<Int64, Int64> instead of your own IntPoint class (if you're on .NET 4.0).
Related
I have this class, where I have Object Equals overriden:
public class Foo
{
public string string1 { get; set; }
public string string2 { get; set; }
public string string3 { get; set; }
public override bool Equals(object other)
{
if (!(other is Foo)) return false;
Foo otherFoo = (other as Foo);
return otherFoo.string1 == string1 && otherFoo.string2 == string2 && otherFoo.string3 == string3;
}
}
I get a warning "overrides object.equals but not object.gethashcode" of which I understand the need of overriding the GetHashCode, for my type to behave according to a hashable type.
As far as I researched, for this code to be unique usually the XOR operator is used, or prime number multiplications are involved. So according to my sources, source1 and source2 I was considering this two options for my GesHashCode override method.
1:
public override int GetHashCode() {
return string1.GetHashCode() ^ string2.GetHashCode() ^ string3.GetHashCode();
}
2:
public override int GetHashCode() {
return (string1 + string2 + string3).GetHashCode();
}
I am not sure either if this approaches ensures the purpose of the GetHashCode override in my case, that is to eliminate the compilation warning, and by the way ensure that the type can be handeled in collections properly, which I believe thas is that if the values they hold are equal to be considered equal, but if equal values on diferent instances take place in a collection, each needs to be found accordingly.
In the case of both of the approaches being valid, I wonder which one might be better and why.
There's a fairly simple but effective way to do this:
public override int GetHashCode()
{
unchecked // Hash code calculation can overflow.
{
int hash = 17;
hash = hash * 23 + firstItem.GetHashCode();
hash = hash * 23 + secondItem.GetHashCode();
// ...and so on for each item.
return hash;
}
}
Where firstItem, secondItem and so on are the items which contribute to the hash code. (Larger primes can also be used instead of 17 and 23, but it really doesn't make much difference.)
However note that if you're using .Net Core 3.1, you can do this instead:
public override int GetHashCode() => HashCode.Combine(firstItem, secondItem, ...etc);
Incidentally, if anyone wants to look at the implementation of HashCode.Combine(), it's here.
It's a lot more sophisticated than the code I posted. :)
this is my Clients class:
public class Clients
{
public string Email { get; set; }
public string Name { get; set; }
public Clients(string e, string n)
{
Email = e;
Name = n;
}
I want to make a new list which contains the same clients from List A and List B .
For example:
List A - John, Jonathan, James ....
List B - Martha, Jane, Jonathan ....
Unsubscribers - Jonathan
public static List<Clients> SameClients(List<Clients> A, List<Clients> B)
{
List<Clients> Unsubscribers = new List<Clients>();
Unsubscribers = A.Intersect(B).ToList();
return Unsubscribers;
}
However for some reasons I get empty list and I have no idea what's wrong.
The problem is that when you are comparing objects Equals and Gethashcode are used to compare them. You can override these two methods and provide your own implementation based on your needs...there is already an answer below covering how to override these two methods
However, normally I prefer to keep my entities/models (or whatever you want to call them) very simple and keep comparison implementation details away from my models. In that case, you can implement an IEqualityComparer<TSource> and use an overload of Intersects that takes in an IEqualityComparer
Here's an example implementation of IEqualityComprarer based on only the Name property...
public class ClientNameEqualityComparer : IEqualityComparer<Clients>
{
public bool Equals(Clients c1, Clients c2)
{
if (c2 == null && c1 == null)
return true;
else if (c1 == null | c2 == null)
return false;
else if(c1.Name == c2.Name)
return true;
else
return false;
}
public int GetHashCode(Client c)
{
return c.Name.GetHashCode();
}
}
Basically, the implementation above only cares about the Name property, if two instances of Clients have the same value for the Name property, then they are considered equal.
Now you can do the followig...
A.Intersect(B, new ClientNameEqualityComparer()).ToList();
And that will produce the results you are expecting...
Intersect uses GetHashCode and Equals by default, but you haven't overriden it, so Object.Equals is used which just compares references. Since all your client-instances are initialized with new they are separate instances even if they have equal values. That's why Intersect "thinks" that there are no common clients.
So you have several options.
implement a custom IEqualityComparer<Clients> and pass that to Intersect(or many other LINQ methods). This has the advantage that you could implement different comparer for different requirements and you don't need to modify the original class
let Clients override Equals and GetHashCode and /or
let Clients implement IEquatable<Clients>
For example(showing the last two because other answer showed already IEqualityComparer<T>):
public class Clients : IEquatable<Clients>
{
public string Email { get; set; }
public string Name { get; set; }
public Clients(string e, string n)
{
Email = e;
Name = n;
}
public override bool Equals(object obj)
{
return obj is Clients && this.Equals((Clients)obj);
}
public bool Equals(Clients other)
{
return Email == other?.Email == true
&& Name == other?.Name == true;
}
public override int GetHashCode()
{
unchecked
{
int hash = 17;
hash = hash * 23 + (Email?.GetHashCode() ?? 0);
hash = hash * 23 + (Name?.GetHashCode() ?? 0);
return hash;
}
}
}
Worth reading:
Differences between IEquatable<T>, IEqualityComparer<T>, and overriding .Equals() when using LINQ on a custom object collection?
I've got a class:
class ThisClass
{
private string a {get; set;}
private string b {get; set;}
}
I would like to use the Intersect and Except methods of Linq, i.e.:
private List<ThisClass> foo = new List<ThisClass>();
private List<ThisClass> bar = new List<ThisClass>();
Then I fill the two lists separately. I'd like to do, for example (and I know this isn't right, just pseudo code), the following:
foo[a].Intersect(bar[a]);
How would I do this?
If you want a list of a single property you'd like to intersect then all the other pretty LINQ solutions work just fine.
BUT! If you'd like to intersect on a whole class though and as a result have a List<ThisClass> instead of List<string> you'll have to write your own equality comparer.
foo.Intersect(bar, new YourEqualityComparer());
same with Except.
public class YourEqualityComparer: IEqualityComparer<ThisClass>
{
#region IEqualityComparer<ThisClass> Members
public bool Equals(ThisClass x, ThisClass y)
{
//no null check here, you might want to do that, or correct that to compare just one part of your object
return x.a == y.a && x.b == y.b;
}
public int GetHashCode(ThisClass obj)
{
unchecked
{
var hash = 17;
//same here, if you only want to get a hashcode on a, remove the line with b
hash = hash * 23 + obj.a.GetHashCode();
hash = hash * 23 + obj.b.GetHashCode();
return hash;
}
}
#endregion
}
Maybe
// returns list of intersecting property 'a' values
foo.Select(f => f.a).Intersect(bar.Select(b => b.a));
BTW property a should be public.
Not sure of the speed of this compared to intersect and compare but how about:
//Intersect
var inter = foo.Where(f => bar.Any(b => b.a == f.a));
//Except - values of foo not in bar
var except = foo.Where(f => !bar.Any(b => b.a == f.a));
foo.Select(x=>x.a).Intersect(bar.Select(x=>x.a))
What exactly is the desired effect? Do you want to get a list of strings composed of all the a's in your classes, or a list of ThisClass, when two ThisClass instances are identified via unique values of a?
If it's the former, the two answers from #lazyberezovksy and #Tilak should work. If it's the latter, you'll have to override IEqualityComparer<ThisClass> or IEquatable<ThisClass> so that Intersect knows what makes two instances of ThisClass equivalent:
private class ThisClass : IEquatable<ThisClass>
{
private string a;
public bool Equals(ThisClass other)
{
return string.Equals(this.a, other.a);
}
}
then you can just call:
var intersection = foo.Intersect(bar);
I know this is old but couldn't you also just override the Equals & GetHashCode on the class itself?
class ThisClass
{
public string a {get; set;}
private string b {get; set;}
public override bool Equals(object obj)
{
// If you only want to compare on a
ThisClass that = (ThisClass)obj;
return string.Equals(a, that.a/* optional: not case sensitive? */);
}
public override int GetHashCode()
{
return a.GetHashCode();
}
}
You should create IEqualityComparer. You can pass the IEqualityComparer to Intersect() method. This will help you get List(which intersect with bar) easier.
var intersectionList = foo.Intersect(bar, new ThisClassEqualityComparer()).ToList();
class ThisClassEqualityComparer : IEqualityComparer<ThisClass>
{
public bool Equals(ThisClass b1, ThisClass b2)
{
return b1.a == b2.a;
}
public int GetHashCode(Box bx)
{
// To ignore to compare hashcode, please consider this.
// I would like to force Equals() to be called
return 0;
}
}
I want to use a custom generic class as a key in a dictionary. How should I override Equals and GetHashCode?
Eg,
public class SomeKey<T,V>
{
public T Value1 { get; set; }
public V Value2 { get; set; }
public SomeKey(T val1, V val2)
{
this.Value1 = val1;
this.Value2 = val2;
}
public override bool Equals(SomeKey<T,V> otherKey)
{
//whats the best option here?
}
public override int GetHashCode()
{
//whats the best option here?
}
}
Thanks
Equality is simple: test for Value1 and Value2 being equal.
For the hash code the simplest approach is to use xor to combine the hash codes from Value1 and Value2.
public override bool Equals(SomeKey<T,V> otherKey)
{
return Value1.Equals(otherKey.Value1) && Value2.Equals(otherKey.Value2);
}
public override int GetHashCode()
{
return Value1.GetHashCode() ^ Value2.GetHashCode();
}
There are lots of alternative ways of calculating the hash code. If performance is a bottleneck then you should consider something more tailored than xor.
For example, Stack Overflow offers these links (and many more):
Custom type GetHashCode
What is the best algorithm for an overridden System.Object.GetHashCode?
You should override it in a way that GetHashcode reliably returns the same value for the same object, and Equals to always return true for the same objects. The msdn has some advices for implementing GetHashcode (the remarks section).
I have a List<MyClass> someList.
class MyClass
{
public int Prop1...
public int Prop2...
public int Prop3...
}
I would like to know how to get a new distinct List<MyClass> distinctList from List<MyClass> someList, but only comparing it to Prop2.
You can emulate the effect of DistinctBy using GroupBy and then just using the first entry in each group. Might be a bit slower that the other implementations though.
someList.GroupBy(elem=>elem.Prop2).Select(group=>group.First());
Unfortunately there's no really easy built-in support for this in the framework - but you can use the DistinctBy implementation I have in MoreLINQ.
You'd use:
var distinctList = someList.DistinctBy(x => x.Prop2).ToList();
(You can take just the DistinctBy implementation. If you'd rather use a Microsoft implementation, I believe there's something similar in the System.Interactive assembly of Reactive Extensions.)
you need to use .Distinct(..); extension method.
Here's a quick sample:
public class Comparer : IEqualityComparer<Point>
{
public bool Equals(Point x, Point y)
{
return x.X == y.X;
}
public int GetHashCode(Point obj)
{
return (int)obj.X;
}
}
Do not forget about GetHashCode.
Usage:
List<Point> p = new List<Point>();
// add items
p.Distinct(new Comparer());
Override Equals(object obj) and GetHashCode() methods:
class MyClass
{
public int Prop1 { get; set; }
public int Prop2 { get; set; }
public int Prop3 { get; set; }
public override bool Equals(object obj)
{
return ((MyClass)obj).Prop2 == Prop2;
}
public override int GetHashCode()
{
return Prop2.GetHashCode();
}
}
and then just call:
List<MyClass> distinctList = someList.Distinct().ToList();
Since the introduction of value tuples, if you want a LINQ equivalent to SQL's DISTINCT
items.GroupBy(item => (item.prop1, item.prop2, ...)).Select(group => group.First())
If you would like to Distinct your list by multiple fields, You have to create an instance of IEqualityComparer interface:
public class MyComparer : IEqualityComparer<MyModel>
{
public bool Equals(MyModel x, MyModel y)
{
// compare multiple fields
return
x.Field1 == y.Field1 &&
x.Field2 == y.Field2 &&
x.Field3 == y.Field3 ;
}
public int GetHashCode(MyModel obj)
{
return
obj.Field1.GetHashCode() +
obj.Field2.GetHashCode() +
obj.Field3.GetHashCode();
}
}
Then use the comparer to distinct your list:
var distinctedList = myList.Distinct(new MyComparer()).ToList();
I know it's been a while, but I needed the simplest answer and at this time (with .NET 4.5.1) I found the following to be the most straight-forward answer I could get to:
IEnumerable<long> allIds = waitingFiles.Values.Select(wf => wf.groupId).Distinct();
My situation is that I have a ConcurrentDictionary that looks something like:
ConcurrentDictionary<long, FileModel>
The ConcurrentDictionary Values property is basically my List<FileModel>.
*FileModel has a groupId that isn't necessarily unique (though, obviously the key (long) that I use to add the FileModel object into the dictionary is unique to the FileModel).
*Named for clarity in the example.
The point is that I have a large number of FileModels (imagine 100) in the ConcurrentDictionary and within those 100 FileModels there are 5 different groupIds.
At this point I just need a list of the distinct groupId.
So, again if I just had a list of FileModel the code would look like the following:
IEnumerable <long> allIds = allFileModel.Select(fm => fm.groupId).Distinct();