默认排序问题
windows排序
Windows的资源管理中,提供了文件名的智能排序功能,可以识别出文件名中数字(数字位数不相同),然后比较数字大小进行排序,如下图:
代码默认排序
但在C#中的列表排序中则是按照从左到右一个一个字符进行比较进行排序,如下图:
List<string> list=new List<string>(); list.Add("文件(11)"); list.Add("文件(22)"); list.Add("文件(1)"); list.Add("文件(2)"); list.Add("文件(3)"); list.Add("文件(4)"); list.Sort(); list.ForEach(l=>Console.WriteLine(l));
运行效果
排序改进
文件名比较方法
public static int FileNameCompare(string s1, string s2) { MatchCollection matchList1 = Regex.Matches(s1, @"\d+");//找出字符串s1中的数字 MatchCollection matchList2 = Regex.Matches(s2, @"\d+");//找出字符串s2中的数字 int minCount = matchList1.Count >= matchList2.Count ? matchList2.Count : matchList1.Count; for (int i = 0; i < minCount; i++) {//循环数字一一比较 if (matchList1[i].Index != matchList2[i].Index) break;//数字位置不同,直接使用字符串比较 if (s1.Substring(0, matchList1[i].Index) != s2.Substring(0, matchList2[i].Index)) break;//数字之前字符不同,直接使用字符串比较 if (matchList1[i].Value == matchList2[i].Value) continue;//数字相同时,比较下一组数字 int s = matchList1[i].Value.Length - matchList2[i].Value.Length; if (s == 0) break;//数字位数相同,直接使用字符串比较 string temp = ""; if (s > 0) //这里不直接比较数字,是为了对数字之后的字符串再进行比较 { //当s1的数字长度大于s2时,对s2的前面进行补0操作,然后在比较s1与s2字符串 temp = s2; for (int n = 0; n < s; n++) { temp = s2.Insert(matchList2[i].Index, "0"); } int r = s1.CompareTo(temp); return r == 0 ? -1 : r; } if (s < 0) { //当s1的数字长度小于s2时,对s1的前面进行补0操作,然后在比较s1与s2字符串 temp = s1; for (int n = 0; n < Math.Abs(s); n++) { temp = s1.Insert(matchList1[i].Index, "0"); } int r = temp.CompareTo(s2); return r == 0 ? 1 : r; } } return s1.CompareTo(s2); }
方法使用
List<string> list = new List<string>(); list.Add("文件(11)"); list.Add("文件(22)"); list.Add("文(11)件(1)"); list.Add("文(2)件(2)"); list.Add("文件(3)"); list.Add("文件(4)"); list.Sort((m1, m2) => Common.THMethod.FileNameCompare(m1, m2)); list.ForEach(l => Console.WriteLine(l));