C# Remove Duplicates from List with LINQ

C# LINQ do have a Distinct() method that works on simple types:

// An string with non-unique elements
string s = "a|b|c|d|a";

// Split the list and take the distinctive elements
var distinctList = s.Split('|').Distinct().ToArray();

// Re-join the list 
var distinctString = string.Join("|", distinctList);

// Output will be: "a|b|c|d"
Console.WriteLine(distinctString);

For non-simple types, you have 2 options, but first lets make a non-simple type, a class:

public class MyClass
{
    public string Title { get; set; }
    public string Text { get; set; }
}

OPTION 1: IMPLEMENT AN EQUALITYCOMPARER

The equalitycomparer is a class that is specifically designed to compare a specific class. An example that will compare on the Title property of the MyClass looks like this:

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

    public int GetHashCode(MyClass obj) 
    {
        return obj.Title.GetHashCode() ^ obj.Text.GetHashCode();
    }       
}

And to use it:

// Create a list of non-unique titles
List<MyClass> list = new List<MyClass>();
list.Add(new MyClass() { Title = "A", Text = "Text" });
list.Add(new MyClass() { Title = "B", Text = "Text" });
list.Add(new MyClass() { Title = "A", Text = "Text" });

// Get the distinct elements:
var distinctList = list.Distinct(new MyClassDistinctComparer());

// Output is: "A B"
foreach (var myClass in distinctList)
     Console.WriteLine(myClass.Title);

OPTION 2: GROUP AND TAKE FIRST

If an equalitycomparer is too much of a hassle, you can take a shortcut and group the list by the title, and take the first element in each group:

// Make a list of non-unique elements
List<MyClass> list = new List<MyClass>();
list.Add(new MyClass() { Title = "A", Text = "Text" });
list.Add(new MyClass() { Title = "B", Text = "Text" });
list.Add(new MyClass() { Title = "A", Text = "Text" });

// Skip the equalitycomparer. Instead, group by title, and take the first element of each group
var distinctList = list.GroupBy(s => s.Title).Select(s => s.First()).ToArray();

// Output is: "A B"
foreach (var myClass in distinctList)
    Console.WriteLine(myClass.Title);

What happens is, that the GroupBy(s => s.Title) will make 2 groups, one for title “A” with 2 elements, and one for title “B” with 1 element. The Select(s => s.First()) then takes the first element from each group, resulting in a list with unique elements.

MORE TO READ:

About briancaos

Developer at Pentia A/S since 2003. Have developed Web Applications using Sitecore Since Sitecore 4.1.
This entry was posted in .net, .NET Core, c#, General .NET and tagged , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.