List<T>对象中的某一个属性(字符串+数字)排序

本文主要是介绍集合中字符串中有数字的排序问题

先说一下简单的集合排序,循序渐进。

在.net 的framewrok框架中提供的排序方法中,如string.sort() 或ArrayList.Sort()这些基础的排序方法。这两个方法对字符串排序时,如果字符串中含有数字,则不会按数字大小排序

ArrayList list = new ArrayList(4);
list.Add("1");
list.Add("111");
list.Add("111.1");
list.Add("21.1");
list.Add("11.1");
list.Add("21");
list.Add("2.1");
list.Add("2");
list.Add("2.1.1");
list.Add("1.1.1");
list.Add("1.1");
list.Sort();

我们原意希望排序后的顺序为:

1,1.1,1.1.1,2,2.1,2.1.1,11.1,21,21.1,111,111.1

实际排序后的顺序为:

1,1.1,1.1.1,11.1,111,111.1,2,2.1,2.1.1,21,21.1

为了序排序后的效果为我们想要的按字符串中的数值排序,我们必须重写字符串的比较函数。 

代码思路:

算法部分引用了https://www.cnblogs.com/linyechengwei/p/3224200.html 

由于比较两个字符串时,是逐个比较字符,先从第一个字符开始比较,取出两个字符串中的第一个字符比较,如果比较结果是大于,则说明第一个字符串大于第二个字符串,如果小于,则说明第一个字符串小于第二字符串,如果等于,则比较两个字符串中的第二个字符。如果比到最后也是相等,则说明两个字符串一样大,如果有一个字符串要多一些字符,则这个字符串在大一些。

我们改进这个算法:在比较过程中如果发现数字,则先不进行比较,看下一个字符是否为数字,这个取出两个字符串中的数字,按数字的数值大小来进行比较。如果相等再取一个字符进行比较。

    ///<summary>
    ///主要用于字符串有数字的比较。例如目录序号(1,1.1,1.1.1,2,2.1省略号)
    ///</summary>
    public class NumberComparerClass : IComparer
    {
       ///<summary>
       ///比较两个字符串,如果含用数字,则数字按数字的大小来比较。
       ///</summary>
       ///<param name="x"></param>
       ///<param name="y"></param>
       ///<returns></returns>
       int IComparer.Compare( Object x, Object y )
       {
           if(x==null||y==null)
              throw new ArgumentException("Parameters can't be null");
           string fileA = x as string;
           string fileB = y as string;
           char[] arr1   =   fileA.ToCharArray();
           char[] arr2 = fileB.ToCharArray();
           int i = 0, j =0;
           while( i < arr1.Length && j < arr2.Length)
           {
              //注意全角字符的数字问题,会导致int.Parse异常
              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;
           }
       }
    }

 

 调用时的代码如下:
var numberComparer  = new NumberComparerClass ();
List.Sort(numberComparer);
这样排序后的字符串就为按字符串中的数值排序了,为:
1,1.1,1.1.1,11.1,111,111.1,2,2.1,2.1.1,21,21.1

集合中对象的属性排序 

上面是普通的集合排序,那如果我们遇到存储对象的集合里按对象的某一个属性排序,这个属性是字符串加数字类型,有了上面的基础,这个问题就简单多了。

public class TestModel
{
    public string Number { get;set; }
}

public static class Compare
{
       public IEnumerable<TestModel> CompareList(IEnumerable<TestModel> models)
       {
             return models.OrderBy(m => m.Number, new NumberComparerClass()).ToList();
       }
}

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

盛唐华夏

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值