Сравнение строк в С#

Я хочу реализовать пользовательскую строку IComparer в С# и применить ее к ComboBox.

Фактические результаты

Если я устанавливаю свойство ComboBox Sorted в значение true, вывод:

A
AA
AAA
B
BB
BBB

Требуемые результаты

Требуемое поведение алгоритма сортировки следующее (финансовые разработчики поймут, почему:)):

AAA
AA
A
BBB
BB
B

Вопрос

Можно ли это сделать? Нужны ли здесь алгоритмы сортировки?

PS: Мне не нужен полный ответ с кодом, мне просто нужно понять, как это можно сделать.

ИЗМЕНИТЬ

Речь идет о кредитных рейтингах. Я опустил что-то в своем вопросе. Оценки должны быть отсортированы в следующем порядке:

XXX
XX+
XX
XX-
X+
X
X-

с X in ('A','B','C') и 'A' > 'B' > 'C'

Ответ 1

Предполагая, что это относится к кредитным рейтингам, обычно это делается с помощью столбца "порядок сортировки" класса CreditRating, который можно использовать для сортировки списка перед назначением его в качестве источника данных выпадающего списка.

Но быстрый способ обхода (основанный на ограниченных возможных значениях) заключался бы в сортировке по первой восходящей букве, а затем по длине нисходящей строки:

if(left[0] != right[0])
    return left[0].CompareTo(right[0]);
else
    return right.Length - left.Length;

Другим обходным решением, если вы хотите больше контролировать порядок, является создание списка возможных значений в "правильном" порядке, а затем его использование для сортировки списка:

public class MyComparer : IComparer<string>
{
    private static readonly string[] Ratings = new [] {
        "CC","C","CCC-","CCC","CCC+",
        "B-","B","B+","BB-","BB","BB+","BBB-","BBB","BBB+",
        "A-","A","A+","AA-","AA","AA+","AAA"};
    // reverse the order so that any strings not found will be put at the end.

    public int Compare(string left, string right)
    {
       return Array.IndexOf(Ratings, right).CompareTo(Array.IndexOf(Ratings, left));
    }
}

Ответ 2

Здесь в основном реализована версия:

public class MyComparer : IComparer<string>
{
    public int Compare(string x, string y)
    {
        //todo null checks on input

        var pairs = x.Zip(y, (a, b) => new { x = a, y = b });

        foreach (var pair in pairs)
        {
            int value = pair.x.CompareTo(pair.y);
            if (value != 0)
                return value;
        }


        //if we got here then either they are the same,
        //or one starts with the other
        return y.Length.CompareTo(x.Length); //note x and y are reversed here
    }
}

Таким образом, это использует Zip для получения пар символов из каждой соответствующей строки до тех пор, пока не закончится, возвращая соответствующее значение, если они не равны. Если он пройдет мимо, то одна строка начинается с другой. Для традиционного сравнения строк мы просто сравниваем длины в том же порядке, что и входные параметры. Поскольку мы существенно меняем порядок, основанный на длине, обратите внимание, что x и y меняются местами на последней строке. Это меняет логику сравнения.

Ответ 3

Напишите IComparer так, чтобы он принимал строки, но сравнивал их на символ,

if A[0] == B[0] go to the next character.
if B[1] == null or A[1] < B[1], return A < B.
if A[1] == null or B[1] < A[1], return B < A.
if equal...continue as needed