Finding the distinct values of a dictionary

I have a GroupSummary class that has some properties like this in it:

public class GroupsSummary
{
    public bool FooMethod()
    {
      ////
    }
    public bool UsedRow { get; set; }

    public string GroupTin   { get; set; }
    public string PayToZip_4 { get; set; }
    public string PayToName  { get; set; }

    public string PayToStr1     { get; set; }
    public string PayToStr2     { get; set; }
    public string PayToCity     { get; set; }
    public string PayToState    { get; set; }
    public bool   UrgentCare_YN { get; set; }
}

Then I have a Dictionary like <string, List<GroupsSummary>

For each of these dictionary items I want to find all the distinct addresses but the properties of this class that define a distinct address for me are

PayToStr1,PayToStr2,PayToCity,PayToState

I know as far as I can say something like mydictionartItem.select(t => t).Distinct().ToList() but I think that will compare all the properties of this class which is wrong. So how should I solve this?

Upvotes: 5

Views: 188

Answers (4)

L.B
L.B

Reputation: 116108

var newDict = dict.ToDictionary(
                    x=>x.Key, 
                    v=>v.Value.GroupBy(x=>new{x.PayToStr1, x.PayToStr2, x.PayToCity, x.PayToState})
                              .Select(x=>x.First())
                              .ToList());

Upvotes: 4

Nicholas Carey
Nicholas Carey

Reputation: 74197

The easiest way would be to implement an IEqualityComparer<GroupsSummary>

Then you can say something like

HashSet<GroupSummary> unique = new HashSet<GroupsSummary>(
  myDict.Values ,
  new MyGroupsSummaryEqualityComparer()
  ) ;

Upvotes: 2

dbc
dbc

Reputation: 116595

Write your own IEqualityComparer, like so:

    public class GroupsSummaryComparer : IEqualityComparer<GroupsSummary>
    {
        public bool Equals(GroupsSummary x, GroupsSummary y)
        {
            if (object.ReferenceEquals(x, y))
                return true;
            else if (object.ReferenceEquals(x, null) || object.ReferenceEquals(y, null))
                return false;

            return x.PayToStr1 == y.PayToStr1 && x.PayToStr2 == y.PayToStr2 && x.PayToCity == y.PayToCity && x.PayToState == y.PayToState;
        }

        public int GetHashCode(GroupsSummary obj)
        {
            if (obj == null)
                return 0;
            int code;
            if (obj.PayToStr1 != null)
                code ^= obj.PayToStr1.GetHashCode();
            if (obj.PayToStr2 != null)
                code ^= obj.PayToStr2.GetHashCode();
            if (obj.PayToCity != null)
                code ^= obj.PayToCity.GetHashCode();
            if (obj.PayToState != null)
                code ^= obj.PayToState.GetHashCode();
            return code;
        }
    }

Then you can pass it to Distinct

This may be safer than implementing IEquatable<GroupsSummary> directly on the class, since, in other situations, you may want to test them for full equality.

Upvotes: 2

AlwaysAProgrammer
AlwaysAProgrammer

Reputation: 2919

implement IEquatable<T> interface on the GroupsSummary Class. More information can be found here

IEquatable defines a method Equals. Remember to overload the GetHashCode method as well

Upvotes: 2

Related Questions