How to get a distinct list from a List of objects?

C#LinqClassListProperties

C# Problem Overview


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.

C# Solutions


Solution 1 - C#

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());

Solution 2 - C#

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.)

Solution 3 - C#

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());

Solution 4 - C#

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();

Solution 5 - C#

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())

Solution 6 - C#

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();

Solution 7 - C#

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();

Solution 8 - C#

Simple way to remove duplications where all properties are equal:

System.Web.Script.Serialization.JavaScriptSerializer jss = new System.Web.Script.Serialization.JavaScriptSerializer();
serviceList = serviceList.GroupBy(s => jss.Serialize(s)).Select(group => group.First()).ToList();

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionWillemView Question on Stackoverflow
Solution 1 - C#CodesInChaosView Answer on Stackoverflow
Solution 2 - C#Jon SkeetView Answer on Stackoverflow
Solution 3 - C#Ilya SmaginView Answer on Stackoverflow
Solution 4 - C#Waldemar GałęzinowskiView Answer on Stackoverflow
Solution 5 - C#hngr18View Answer on Stackoverflow
Solution 6 - C#Masoud DarvishianView Answer on Stackoverflow
Solution 7 - C#raddevusView Answer on Stackoverflow
Solution 8 - C#Graham LaightView Answer on Stackoverflow