排序字符串列表

时间:2011-05-11 05:46:44

标签: c# regex list sorting

我有一个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 个答案:

答案 0 :(得分:3)

我对您的代码进行了一些修改。问题是当Group 1Group 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);
});

修改
我还在字符串开头添加了_*删除所有_个字符。我假设这些字符串在数字后面只包含_,而不是B1BB1$

这里的事情是你没有真正解释应该如何进行比较,我不得不从你的原始数据和排序数据中假设这些东西,否则如果要排序{{1}会发生什么和A1A?它应该返回什么?

答案 1 :(得分:1)

这是我如何实现这样的比较器。更容易关注恕我直言。

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;
});

答案 2 :(得分:-3)

对于此示例,只需调用sort l_lstTemp.Sort()即可获得您要查找的结果