Сортировка списка строк - PullRequest
2 голосов
/ 11 мая 2011

У меня есть List<String> l_lstTemp, который содержит

"A1"
"A1_1"
"A1_2"
"1A"
"B2_1"
"B1_2"
"B1_1_2"
"A10"
"B11"
"A"
"Z"

Мне нужно отсортировать элементы на основе символьного и числового значения.

Таким образом, отсортированный список будеткак

"1A"
"A"
"A1"
"A1_1"
"A1_2"
"A10"
"B1_1_2"
"B1_2"
"B2_1"
"B11"
"Z"

Вот мой код:

l_lstTemp.Sort(delegate(String One, String Two)
{
    Match l_mOne = Regex.Match(One, @"(\D*)(\d*)");
    Match l_mTwo = Regex.Match(Two, @"(\D*)(\d*)");
    int Result;
    if (l_mOne.Success || l_mTwo.Success)
    {
        String l_strX, l_strY;
        l_strX = l_mOne.Groups[1].Value;
        l_strY = l_mTwo.Groups[1].Value;
        Result = l_strX.CompareTo(l_strY);
        if (Result != 0)
            return Result;
        l_strX = l_mOne.Groups[2].Value;
        l_strY = l_mTwo.Groups[2].Value;
        if (l_strX == String.Empty || l_strY == String.Empty)
        {
            Result = l_strX.CompareTo(l_strY);
            if (Result != 0)
                return Result;
        }
        else
        {
            long X = long.Parse(l_strX);
            long Y = long.Parse(l_strY);
            Result = X.CompareTo(Y);
            if (Result != 0)
                return Result;
        }

    }
    return 0 ;
}
);

Но он не работает (сортировка) должным образом.

Как изменить код для правильной сортировки списка?

Пожалуйста, напишите мне способ сделать это.

Заранее спасибо.

Ответы [ 3 ]

3 голосов
/ 11 мая 2011

Я сделал некоторые изменения в вашем коде. Дело в том, что когда Group 1 и Group 2 равны, вам все еще нужно проверить, что остается .

Важно: Я внес изменения в ваш код, так что это может быть немного сложнее. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

l.Sort(delegate(String One, String Two)
{
    while (One != "" && Two != "")
    {
        if (One == Two)
            return 0;

        //Add one more group to capture what remains of the expression
        Match l_mOne = Regex.Match(One, @"_*(\D*)(\d*)(.*)$"); 
        Match l_mTwo = Regex.Match(Two, @"_*(\D*)(\d*)(.*)$");
        int Result;
        if (l_mOne.Success || l_mTwo.Success)
        {
            String l_strX, l_strY;
            l_strX = l_mOne.Groups[1].Value;
            l_strY = l_mTwo.Groups[1].Value;
            Result = l_strX.CompareTo(l_strY);
            if (Result != 0)
                return Result;
            l_strX = l_mOne.Groups[2].Value;
            l_strY = l_mTwo.Groups[2].Value;
            if (l_strX == String.Empty || l_strY == String.Empty)
            {
                Result = l_strX.CompareTo(l_strY);
                if (Result != 0)
                    return Result;
            }
            else
            {
                long X = long.Parse(l_strX);
                long Y = long.Parse(l_strY);
                Result = X.CompareTo(Y);
                if (Result != 0)
                    return Result;
                One = l_mOne.Groups[3].Value; //Store in 'One' the remaining part of the regex
                Two = l_mTwo.Groups[3].Value; //The same in Two

                continue; //The result will be the result of the comparison of those two new values.
            }

        }
    }
    return One.CompareTo(Two);
});

Edit:
Я также добавил _* к удалить все символы _ с начала строк. Я предположил, что строки будут содержать только _ после чисел, а не что-то вроде B1B или B1$.

Дело в том, что вы на самом деле не объясняете, как следует проводить сравнение, и мне пришлось исходить из этих исходных данных и отсортированных данных, иначе что произойдет, если вы захотите отсортировать A1A и A1_? Что он должен вернуть?

1 голос
/ 11 мая 2011

Вот как бы я реализовал такой компаратор.Гораздо проще следовать ИМХО.

var re = new Regex(@"^(\d+)?([A-Z]+)(\d+)?(?:_(\d+)(?:_(\d+))?)?$");
Func<Group, int, int> intOrDefault = (g, d) => g.Success ? Convert.ToInt32(g.Value) : d;
list.Sort((x, y) =>
{
    var xm = re.Match(x);
    var ym = re.Match(y);
    int cmp;

    // compare the first group
    // compare the leading numbers (if any)
    cmp = intOrDefault(xm.Groups[1], int.MaxValue).CompareTo(intOrDefault(ym.Groups[1], int.MaxValue));
    if (cmp != 0)
        return cmp;
    // compare letters
    cmp = xm.Groups[2].Value.CompareTo(ym.Groups[2].Value);
    if (cmp != 0)
        return cmp;
    // compare the trailing numbers (if any)
    cmp = intOrDefault(xm.Groups[3], 0).CompareTo(intOrDefault(ym.Groups[3], 0));
    if (cmp != 0)
        return cmp;

    // compare the next group
    cmp = intOrDefault(xm.Groups[4], 0).CompareTo(intOrDefault(ym.Groups[4], 0));
    if (cmp != 0)
        return cmp;

    // compare the last group
    cmp = intOrDefault(xm.Groups[5], 0).CompareTo(intOrDefault(ym.Groups[5], 0));
    return cmp;
});
0 голосов
/ 11 мая 2011

В этом примере, просто позвонив sort l_lstTemp.Sort(), вы получите результат, который вы ищете

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...