Список<string> C# пользовательской сортировки. Подчеркивать после цифр

У меня есть список: "a_a", "a1a", "aaa".

Мне нужно отсортировать его следующим образом: "a1a", "a_a", "aaa".

Другими словами, мне нужно, чтобы символы "_" появлялись сразу после цифр, но перед буквами.

Я знаю, что можно использовать пользовательский Comparer, но я не нашел никакого хорошего решения для этой проблемы, только грязные хаки, например:

Compare(string x, string y){

return Comparer.Default.Compare(x.Replace("_", "9z"), y.Replace("_", "9z"));

}

2 ответа

Решение

Согласно стандартной таблице ASCII:

  '0'..'9' have codes 0x30..0x39
  '_'      -/-        0x5F
  'a'..'z' -/-        0x61..0x7A

так как коды расположены в правильном порядке, вы можете использовать порядковое сравнение:

  List<String> list = new List<string> {
    "a1a", "a_a", "aaa"
  };

  list.Sort((Comparison<String>) (
    (String left, String right) => {
       return String.CompareOrdinal(left, right);
    }
  ));

  ...
  // a1a, a_a, aaa
  Console.Write(String.Join(", ", list)); 

Вот пользовательский компаратор строк, который возьмет компаратор символов, так что вы можете сравнивать символы по своему усмотрению. Как говорится, убедитесь, что StringComparer.Ordinal не выполняет работу до внедрения собственных компараторов.

public class CustomStringComparer : IComparer<string>
{
    readonly IComparer<char> charComparer;
    public CustomStringComparer(IComparer<char> charComparer)
    {
        this.charComparer = charComparer;
    }
    public int Compare(string a, string b)
    {
        int result = 0;
        for (int i = 0; (i < a.Length || i < b.Length) && result == 0 ; i++)
        {
            if (i >= a.Length || i >= b.Length)
            {
                return i >= a.Length ? -1 : 1;
            }
            result = charComparer.Compare(a[i], b[i]);
        }
        return result;
    }
}
Другие вопросы по тегам