首页 学海无涯 C#基础 C#使用IComparer接口实现数字字符串排序
C#使用IComparer接口实现数字字符串排序
摘要 在Linq查询表达式中,OrderBy实现了对序列元素的排序,此外OrderBy支持自定义排序规则,本文将通过IComparer接口实现字符串类型的数字升序排序。

环境准备

.NET 5.0

文章正文

一、字符串排序问题

做过.NET开发的都知道,Linq查询表达式中,OrderBy可以实现序列的升序排列。

new string[] { "2", "1", "0", "3", "10", "4", "12", "14", "11", "13" }.OrderBy(s => s).ToArray();

所以,我以为这句代码执行的结果是这样的:

["0", "1", "2", "3", "4", "10", "11", "12", "13", "14"]

然而,他是这样的:


那么,为什么会是这样的?

其实我心里第一反应是字符串排序是按照ASCII码排序,但是好像并没有10,11,12,13,14等对应的ASCII码,这就有点尴尬了。

经过几番百度后,或许找到了一种解释:ASCII码只针对字符,而10,11,12等有两个字符,所以编译器只会认前一个字符,所以10,11,12,13,14等字符串都被看做是'1'这个字符,如此便解释的通了。

二、自定义排序,实现数字字符串升序排序

OrderBy方法有两个重载,其中一个多了一个IComparer<T>类型的参数,通过实现IComparer<T>接口,我们可以自定义排序规则:

public class StringNumberComparer : IComparer<string>
{
        public int Compare(string x, string y)
        {
            if (x == y)
                return 0;
            bool xIsNum = int.TryParse(x, out int xNum);
            bool yIsNum = int.TryParse(y, out int yNum);
            if (xIsNum && yIsNum)
                return xNum > yNum ? 1 : -1;
            else
                return string.CompareOrdinal(x, y);
        }
}

Icomparer<T>接口需要实现Compare方法,比较两个参数,根据泛型类型T来决定两个参数的类型。方法返回0表示x和y相等,返回负数表示x小于y,返回正数表示x大于y。上述代表表示当x和y都可以转为int类型时,按int类型时的大小来决定谁大谁小,否则就按默认的比较方法来决定谁大谁小。

调用OrderBy时传入一个StringNumberComparer对象:

#region 自定义数字字符串排序
{
    var strArr = new string[] { "2", "1", "0", "3", "10", "4", "12", "14", "11", "13" };

    var orderStrArr = strArr.OrderBy(s => s, new StringNumberComparer()).ToArray();

    Console.WriteLine("-----------自定义数字字符串排序-----------");
    Console.WriteLine($"升序排序:{string.Join(",", orderStrArr)}");
}
#endregion

查看运行结果:


成功实现了数字字符串升序排序。

三、总结

通过实现IComparer<T>接口的Compare方法,可以任意自定义规则进行排序的比较,是一个高度开放的API。

跟不落阁,学DOTNET!关注公众号,获取更多干货。


版权声明:本文由不落阁原创出品,转载请注明出处!

本文链接:http://www.leo96.com/article/detail/64

广告位

来说两句吧
最新评论

暂无评论,大侠不妨来一发?