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:
- EqualityComparer Class from Microsoft
- Remove duplicates in the list using linq from StackOverflow