Using GroupBy()
and Count() > 1
I'm trying to find duplicate instances of my class in a list.
The class looks like this:
public class SampleObject
{
public string Id;
public IEnumerable<string> Events;
}
And this is how I instantiate and group the list:
public class Program
{
private static void Main(string[] args)
{
var items = new List<SampleObject>()
{
new SampleObject() { Id = "Id", Events = new List<string>() { "ExampleEvent" } },
new SampleObject() { Id = "Id", Events = new List<string>() { "ExampleEvent" } }
};
var duplicates = items.GroupBy(x => new { Token = x.Id, x.Events })
.Where(g => g.Count() > 1)
.Select(g => g.Key)
.ToList();
}
}
The duplicates
contains no items. How can I make the grouping work?
GroupBy()
will perform a default comparison, causing it to find your lists not equal.See the following code:
Two "equal" lists, right? However, this will print:
So they're not considered equal, hence not grouped.
You need to provide a custom comparer, that will compare the relevant properties of the objects. Note that as shown before,
List<T>.GetHashCode()
does not properly represent the items in the list.You can do that as such (from Good GetHashCode() override for List of Foo objects respecting the order and LINQ GroupBy on multiple ref-type fields; Custom EqualityComparer):
And use it like this:
To get objects to work with many of LINQ's operators, such as
GroupBy
orDistinct
, you must either implementGetHashCode
&Equals
, or you must provide a custom comparer.In your case, with a property as a list you probably need a comparer, unless you made the list read only.
Try this comparer:
Now this code works:
List<T>
has no overriddenEquals
+GetHashCode
, that's why yourGroupBy
doesn't work as expected. One of the two properties of the anonymous type refer to the list, when theGroupBy
has to compare two listsObject.RefernceEquals
is used which only checks if both are the same reference and not if both contain the sample elements.You could provide a custom
IEqualityComparer<T>
:Then you can use it in many LINQ methods like also
GroupBy
: