C#按字串中的數字排序問題

weixin_34162695發表於2017-02-07

在專案的開發中遇到這麼個問題,原本應該是按照丐幫1, 丐幫2, 丐幫3 ....的順序進行排序的,這裡的順序卻成了 丐幫1, 丐幫10, 丐幫11...

728712-25f441737fd9a56d.png
分組列表

問題
在.net的framework框架中提供的排序方法, 如List<T>.Sort()方法,對字串進行排序時,如果字串中含有數字,則不會按數字大小進行排序。

解決方案
為了序排序後的效果為我們想要的按字串中的數值排序,我們必須重寫字串的比較函式。

程式碼思路
由於比較兩個字串時,是逐個比較字元,先從第一個字元開始比較,取出兩個字串中的第一個字元比較,如果比較結果是大於,則說明第一個字串大於第二個字串,如果小於,則說明第一個字串小於第二字串,如果等於,則比較兩個字串中的第二個字元。如果比到最後也是相等,則說明兩個字串一樣大,如果有一個字串要多一些字元,則這個字串在大一些。
我們改進這個演算法:在比較過程中如果發現數字,則先不進行比較,看下一個字元是否為數字,這個取出兩個字串中的數字,按數字的數值大小來進行比較。如果相等再取一個字元進行比較。

程式碼實現:(這裡的Team為自定義的物件)

public class TeamNameComparer : IComparer<Team>
    {
        public int Compare(Team x, Team y)
        {
            if (x == null || y == null)
            {
                throw new ArgumentException("Parameters can't be null");
            }

            var nameA = x.Name as string;
            var nameB = y.Name as string;
            var arr1 = nameA.ToCharArray();
            var arr2 = nameB.ToCharArray();

            var i = 0;
            var j = 0;

            while (i < arr1.Length && j < arr2.Length)
            {
                if (char.IsDigit(arr1[i]) && char.IsDigit(arr2[j]))
                {
                    string s1 = "", s2 = "";
                    while (i < arr1.Length && char.IsDigit(arr1[i]))
                    {
                        s1 += arr1[i];
                        i++;
                    }
                    while (j < arr2.Length && char.IsDigit(arr2[j]))
                    {
                        s2 += arr2[j];
                        j++;
                    }
                    if (int.Parse(s1) > int.Parse(s2))
                    {
                        return 1;
                    }
                    if (int.Parse(s1) < int.Parse(s2))
                    {
                        return -1;
                    }
                }
                else
                {
                    if (arr1[i] > arr2[j])
                    {
                        return 1;
                    }
                    if (arr1[i] < arr2[j])
                    {
                        return -1;
                    }
                    i++;
                    j++;
                }
            }

            if (arr1.Length == arr2.Length)
            {
                return 0;
            }
            else
            {
                return arr1.Length > arr2.Length ? 1 : -1;
            }
        }
    }

修改後的排序為:

728712-70815df2c84e4032.png
排序後的分組列表

相關文章