排序字符串数

可能重复:
C#中的自然排序顺序

我有一个包含大量数字的列表。 但由于一些额外的字母,它们被保存为字符串。

我的列表看起来像这样:

1 10 11 11a 11b 12 2 20 21a 21c A1 A2 ... 

但它看起来应该是这样的

 1 2 10 11a 11b ... A1 A2 ... 

如何对列表进行排序以获得此结果?

按照之前的评论,我还将实现一个自定义IComparer类。 根据我的收集,项目的结构可以是数字,也可以是数字后跟字母的组合。 如果是这种情况,则以下IComparer实现应该可行。

 public class CustomComparer : IComparer { public int Compare(string x, string y) { var regex = new Regex("^(d+)"); // run the regex on both strings var xRegexResult = regex.Match(x); var yRegexResult = regex.Match(y); // check if they are both numbers if (xRegexResult.Success && yRegexResult.Success) { return int.Parse(xRegexResult.Groups[1].Value).CompareTo(int.Parse(yRegexResult.Groups[1].Value)); } // otherwise return as string comparison return x.CompareTo(y); } } 

使用此IComparer ,您将能够通过执行操作对string列表进行排序

 var myComparer = new CustomComparer(); myListOfStrings.Sort(myComparer); 

这已通过以下项目测试:

2, 1, 4d, 4e, 4c, 4a, 4b, A1, 20, B2, A2, a3, 5, 6, 4f, 1a

并给出结果:

1, 1a, 2, 20, 4a, 4b, 4c, 4d, 4e, 4f, 5, 6, A1, A2, a3, B2

好吧,您需要从每个字符串中提取数字,然后根据数字列表将字符串列表排序为键。 分两步完成。

要从每个字符串中提取数字,我认为最简单的方法是使用正则表达式 – 查找(\d+)的匹配项(如果您有负数或十进制数字,则必须使用不同的正则表达式)。 假设您在名为ExtractNumber的函数中执行了此操作

现在您可以使用一些创意LINQ进行排序,如下所示:

 strings.Select(s=>new { key=ExtractNumber(s), value=s }) // Create a key-value pair .OrderBy(p=>p.key) // Sort by key .Select(p=>p.Value); // Extract the values 

由于这包括许多字符串操作,正则表达式等,我不认为它是一个有效的算法,但它似乎工作。

 List list1 = new List() { "11c22", "1", "10", "11", "11a", "11b", "12", "2", "20", "21a", "21c", "A1", "A2" }; List list2 = new List() { "File (5).txt", "File (1).txt", "File (10).txt", "File (100).txt", "File (2).txt" }; var sortedList1 = NaturalSort(list1).ToArray(); var sortedList2 = NaturalSort(list2).ToArray(); 

 public static IEnumerable NaturalSort(IEnumerable list) { int maxLen = list.Select(s => s.Length).Max(); Func PaddingChar = s => char.IsDigit(s[0]) ? ' ' : char.MaxValue; return list .Select(s => new { OrgStr = s, SortStr = Regex.Replace(s, @"(\d+)|(\D+)", m => m.Value.PadLeft(maxLen, PaddingChar(m.Value))) }) .OrderBy(x => x.SortStr) .Select(x => x.OrgStr); } 

我是C#的新手,但这是我在Java中欣赏的解决方案:你需要分两步完成,首先定义一个自定义的IComparer,然后在调用sort方法时再使用它。 所以你应该能够做到这样的事情:

 public class MyListSorter : IComparer { public int Compare(MyObject obj1, MyObject obj2) { if ( !Char.IsNumber(obj1) && Char.IsNumber(obj2) ) { return 0; } else if ( Char.IsNumber(obj1) && !Char.IsNumber(obj2) ) { return 1; } else { return obj2.CompareTo(obj1); } } } 

然后

 myObjectList.Sort(new MyListSorter()); 

有关IComparer的更多信息: http : //support.microsoft.com/kb/320727