Jay
Jay

Reputation: 2285

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.

Upvotes: 18

Views: 23402

Answers (3)

David V
David V

Reputation: 11699

You can use Distinct overload with an IEqualityComparer.

Your equals method for your IEqualityComparer implementation would look like this:

bool Equals(TimeMetric x, TimeMetric y)
{
  return x.MetricText.Equals(y.MetricText);
}

Upvotes: 3

Ritch Melton
Ritch Melton

Reputation: 11598

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

Upvotes: 15

Jon
Jon

Reputation: 437376

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

Upvotes: 21

Related Questions