C#订购一个字母数字列表

时间:2016-01-06 19:12:35

标签: c# linq sorting

假设我有一个多部分问题列表,每个问题都有一个问题编号,如11a1b22a和等等。我想使用linq-to-entities从数据库中获取问题列表,但是按QuestionNumber排序。问题是,它不是使用正确的顺序,而是使用像

这样的词典排序
1
11
11a
11b
1a
1b
2
22

到目前为止我所拥有的是自定义比较器:

public class QuestionCompare : IComparer<Question>
{
    public int Compare(Question x, Question y)
    {
        string a = x.QuestionNumber;
        string b = y.QuestionNumber;

        if (a == b)
        {
            return 0;
        }

        int aInt;
        bool aBool = Int32.TryParse(new String(a.Where(Char.IsDigit).ToArray()), out aInt);
        int bInt;
        bool bBool = Int32.TryParse(new String(b.Where(Char.IsDigit).ToArray()), out bInt);
        if (aBool)
        {
            if (bBool)
            {
                if (aInt > bInt)
                {
                    return 1;
                }
                else if (aInt < bInt)
                {
                    return -1;
                }
                else
                {
                    string aLetter = new String(a.Where(Char.IsLetter).ToArray());
                    string bLetter = new String(a.Where(Char.IsLetter).ToArray());
                    return StringComparer.CurrentCulture.Compare(aLetter, bLetter);
                }
            }
            else
            {
                return 1;
            }
        }
        else
        {
            if (bBool)
            {
                return -1;
            }
            else
            {
                return StringComparer.CurrentCulture.Compare(a, b);
            }
        }

        return 0;
    }
}

您可以致电Array.Sort(questionArray,new QuestionCompare())以正确的顺序提问。

但是,我觉得这是一个常见的,定义明确的顺序,所以我想知道是否有更好的实现,甚至是内置于.Net框架的内容。

1 个答案:

答案 0 :(得分:1)

这个比较器工作正常,而且相当短。

public class QuestionCompare : IComparer<Question>
{
    public int Compare(Question x, Question y)
    {
        string a = x.QuestionNumber;
        string b = y.QuestionNumber;

        var aDigits = new string(a.TakeWhile(c => char.IsDigit(c)).ToArray());
        var bDigits = new string(b.TakeWhile(c => char.IsDigit(c)).ToArray());

        int aInt = String.IsNullOrEmpty(aDigits) ? 0 : int.Parse(aDigits);
        int bInt = String.IsNullOrEmpty(bDigits) ? 0 : int.Parse(bDigits);

        return aInt != bInt ? aInt.CompareTo(bInt) : a.CompareTo(b);
    }
}