How to use custom IComparer for SortedDictionary?
Asked Answered
K

2

11

I am having difficulties to use my custom IComparer for my SortedDictionary<>. The goal is to put email addresses in a specific format ([email protected]) as the key, and sort by last name. When I do something like this:

public class Program
{
  public static void Main(string[] args)
  {
    SortedDictionary<string, string> list = new SortedDictionary<string, string>(new SortEmailComparer());
    list.Add("[email protected]", "value1");
    list.Add("[email protected]", "value2");
    foreach (KeyValuePair<string, string> kvp in list)
    {
      Console.WriteLine(kvp.Key);
    }
    Console.ReadLine();
  }
}

public class SortEmailComparer : IComparer<string>
{
  public int Compare(string x, string y)
  {
    Regex regex = new Regex("\\b\\w*@\\b",
                        RegexOptions.IgnoreCase
                        | RegexOptions.CultureInvariant
                        | RegexOptions.IgnorePatternWhitespace
                        | RegexOptions.Compiled
                        );

    string xLastname = regex.Match(x).ToString().Trim('@');
    string yLastname = regex.Match(y).ToString().Trim('@');
    return xLastname.CompareTo(yLastname);
  }
}

I get this ArgumentException: An entry with the same key already exists. when adding the second item.

I haven't worked with a custom IComparer for a SortedDictionary before, and I fail to see my error , what am I doing wrong?

Knesset answered 27/4, 2010 at 9:22 Comment(0)
C
6

If the 2 lastNames are equal then compare for example the whole email like:

int comp = xLastname.CompareTo(yLastname);
if (comp == 0)
   return x.CompareTo(y);
return comp;

Actually, sorteddictionary comparison is also used to distinguish amongst keys* , so you must specify a complete comparison (not only your sorting strategy)

EDIT: * I mean in sortedDictionary 2 keys are equal if Comparer gives 0

Coenzyme answered 27/4, 2010 at 9:28 Comment(1)
Thanks. This was the simple elegant solution.Knesset
U
1

Well, I haven't taken apart your comparer - but it looks like it's just comparing by last name, and you're trying to add the same last name (johansson) twice. That should give you an ArgumentException.

What did you want to happen - and what do you want your comparer to do?

Perhaps you want to sort by last name and then first name? That way you can have two email addresses with the same last name but different first names, and have them still be in the dictionary together, ordered by first name.

Umbrageous answered 27/4, 2010 at 9:26 Comment(1)
Indeed, your assumptions are correct. @Coenzyme provided the solution I wanted, and @Foxfire explained why.Knesset

© 2022 - 2024 — McMap. All rights reserved.