Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Removing duplicate objects in a list (C#)

So I understand how to remove duplicates in a list when it comes to strings and int, etc by using Distinct() from Linq. But how do you remove duplicates based on a specific attribute of an object?

For example, I have a TimeMetric class. This TimeMetric class has two attributes: MetricText and MetricTime. I have a list of TimeMetrics called MetricList. I want to remove any duplicates TimeMetric with the same MetricText attribute. The TimeMetric value can be the same but if any TimeMetric has the same MetricText, it must be unduplicated.

like image 316
Jay Avatar asked Nov 29 '11 16:11

Jay


People also ask

How do I remove duplicates from a list in C sharp?

Use the Distinct() method to remove duplicates from a list in C#.

Can list have duplicates in C#?

In order to allow short circuiting if the duplicate exists early in the list, you can add a HashSet<T> and check the return value of its . Add method. By using . Any you can short circuit the enumeration as soon as you find a duplicate.

How do I remove duplicates from a filtered list?

In Excel, there are several ways to filter for unique values—or remove duplicate values: To filter for unique values, click Data > Sort & Filter > Advanced. To remove duplicate values, click Data > Data Tools > Remove Duplicates.


2 Answers

You need to use the second overload of Distinct that takes an IEqualityComparer<TimeMetric> instance as a second parameter. Define a comparer like this:

class MyComparer : IEqualityComparer<TimeMetric>
{
    public bool Equals(TimeMetric x, TimeMetric y)
    {
        return x.MetricText.Equals(y.MetricText);
    }

    public int GetHashCode(TimeMetric obj)
    {
        return obj.MetricText.GetHashCode();
    }
}

Important note: The above code does not check for the case where the MetricText property is null (and it sounds like it could be, since it's most probably a string). You should do that and return 0 from GetHashCode if MetricText is null. On the other hand, if the type of MetricText is a value type, you don't need to perform any modification.

And then:

var list = new List<TimeMetric> { ... };
var unique = list.Distinct(new MyComparer());
like image 139
Jon Avatar answered Nov 07 '22 02:11

Jon


Use linq:

var list = list 
    .GroupBy(i => i.MetricText)
    .Select(g => g.First())
    .ToList();

Or pass in a comparer that uses the property:

public class mtCompare : IEqualityComparer<TimeMetric>
{
  public bool Equals(TimeMetric x, TimeMetric y)
  {
    return Equals(x.MetricText, y.MetricText);
  }

  public int GetHashCode(TimeMetric obj)
  {
    return obj.MetricText.GetHashCode();
  }
}

....

list.Distinct(new mtCompare());
like image 25
Ritch Melton Avatar answered Nov 07 '22 03:11

Ritch Melton