Click here to Skip to main content
15,898,790 members
Please Sign up or sign in to vote.
1.00/5 (2 votes)
See more:
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.
Posted
Comments
Sergey Alexandrovich Kryukov 13-Jul-12 18:44pm    
Do you require to find an already implemented pattern, or do you agree to simply right it from scratch, without LINQ? You could just implement it ad-hoc or add your own extension method, both things are pretty easy...
--SA
Sergey Alexandrovich Kryukov 14-Jul-12 23:12pm    
And please do not re-post. Ask one question on the topic and use "Improve question" if you need it.
--SA

A little easier is to use the groupby, although a little confusing:

C#
var groups = strings.GroupBy(i => i.str1);
foreach (var group in groups)
{
    var firstGroup = group.First();
    Console.WriteLine(first.str1, first.str2}
}


I used the following class for this:

C#
public class test
{
    public string str1 { get; set; }
    public string str2 { get; set; }
}
 
Share this answer
 
See my answer to your other topic here: removing duplicate objects in a list based on its properties[^]
 
Share this answer
 
Edited: I didn't follow the link in the solution posted by Zoltán Zörgő before my posting. It is essentially the same as what I posted here. I have upvoted his solution.

Distinct() has an overload that takes an IEqualityComparer<TSource> parameter. So you could implement that interface and then use the Distinct() pattern you already know.
Like this:
C#
using System;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleApplication1
{
  class Program
  {
    static void Main(string[] args)
    {
      var metrics = new List<TimeMetric>();
      Random r = new Random();
      for (int i = 0; i < 10; i++)
      {
        var item = new TimeMetric();
        item.MetricText = (i | 1).ToString(); // ensure there are duplicate Text
        item.MetricTime = TimeSpan.FromTicks(r.Next()); // but not duplicate Time
        metrics.Add(item);
        Console.WriteLine("metric[{0}]: MetricText = \"{1}\", MetricTime = {2}",
                          i, item.MetricText, item.MetricTime);
      }
      var NoDuplicates = metrics.Distinct(new TimeMetricTextComparer());
      int ix = 0;
      foreach (var item in NoDuplicates)
      {
        Console.WriteLine("NoDuplicates[{0}]: MetricText = \"{1}\", MetricTime = {2}",
                          ix++, item.MetricText, item.MetricTime);
      }
    }
  }

  class TimeMetric
  {
    public string MetricText { get; set; }
    public TimeSpan MetricTime { get; set; }
  }

  class TimeMetricTextComparer : IEqualityComparer<TimeMetric>
  {
    #region IEqualityComparer<TimeMetric> Members
    public bool Equals(TimeMetric x, TimeMetric y)
    {
      return string.Equals(x.MetricText, y.MetricText);
    }
    public int GetHashCode(TimeMetric obj)
    {
      return obj.MetricText.GetHashCode();
    }
    #endregion
  }
}

In the comparer class, Equals and GetHashCode must be consistent. If Equals is true for two TimeMetric instances, then GetHashCode must return the same value for both.
 
Share this answer
 
v3

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900