How to use custom IComparer for SortedDictionary?

2019-04-21 19:53发布

I am having difficulties to use my custom IComparer for my SortedDictionary<>. The goal is to put email addresses in a specific format (firstnam.lastname@domain.com) 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("a.johansson@domain.com", "value1");
    list.Add("b.johansson@domain.com", "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?

2条回答
在下西门庆
2楼-- · 2019-04-21 20:31

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.

查看更多
啃猪蹄的小仙女
3楼-- · 2019-04-21 20:43

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

查看更多
登录 后发表回答