如何将数字字符串整理为数字?

如果你有像这样的字符串:

"file_0" "file_1" "file_2" "file_3" "file_4" "file_5" "file_6" "file_11" 

如何对它们进行排序,使“file_11”不会出现在“file_1”之后,而是出现在“file_6”之后,因为11> 6。

我是否必须解析字符串并将其转换为数字?

Win7中的Windows资源管理器按我想要的方式对文件进行排序。

您可以导入StrCmpLogicalW函数并使用它来对字符串进行排序。 这与Explorer本身用于文件名的function完全相同。

但是,如果您不想要P / Invoke或在其他系统上保持兼容,则无法帮助您。

我是否必须解析字符串并将其转换为数字?

基本上,是的; 但LINQ可能有所帮助:

 var sorted = arr.OrderBy(s => int.Parse(s.Substring(5))); foreach (string s in sorted) { Console.WriteLine(s); } 

要处理任何类型格式的混合字符串和数字的排序,您可以使用这样的类将字符串拆分为字符串和数字组件并进行比较:

 public class StringNum : IComparable { private List _strings; private List _numbers; public StringNum(string value) { _strings = new List(); _numbers = new List(); int pos = 0; bool number = false; while (pos < value.Length) { int len = 0; while (pos + len < value.Length && Char.IsDigit(value[pos+len]) == number) { len++; } if (number) { _numbers.Add(int.Parse(value.Substring(pos, len))); } else { _strings.Add(value.Substring(pos, len)); } pos += len; number = !number; } } public int CompareTo(StringNum other) { int index = 0; while (index < _strings.Count && index < other._strings.Count) { int result = _strings[index].CompareTo(other._strings[index]); if (result != 0) return result; if (index < _numbers.Count && index < other._numbers.Count) { result = _numbers[index].CompareTo(other._numbers[index]); if (result != 0) return result; } else { return index == _numbers.Count && index == other._numbers.Count ? 0 : index == _numbers.Count ? -1 : 1; } index++; } return index == _strings.Count && index == other._strings.Count ? 0 : index == _strings.Count ? -1 : 1; } } 

例:

 List items = new List { "item_66b", "999", "item_5", "14", "file_14", "26", "file_2", "item_66a", "9", "file_10", "item_1", "file_1" }; items.Sort((a,b)=>new StringNum(a).CompareTo(new StringNum(b))); foreach (string s in items) Console.WriteLine(s); 

输出:

 9 14 26 999 file_1 file_2 file_10 file_14 item_1 item_5 item_66a item_66b 

以下基于Joey建议的代码适用于我(扩展方法为string []):

 public static void SortLogical(this string[] files) { Array.Sort(files, new Comparison(StrCmpLogicalW)); } [DllImport("shlwapi.dll", CharSet=CharSet.Unicode, ExactSpelling=true)] private static extern int StrCmpLogicalW(String x, String y); 

一个简单的方法是填充数字部分,如下所示:

 file_00001 file_00002 file_00010 file_00011 

等等

但这就是知道数字部分可以采用的最大值。

我刚才在一个项目中使用了以下方法。 它不是特别有效,但如果要排序的项目数量不是很大,那么它的表现就足够了。 它的作用是将字符串拆分为比较为'_'字符的数组,然后比较数组的每个元素。 尝试将最后一个元素解析为int,并在那里进行数值比较。

如果输入字符串包含不同数量的元素,它也会提前退出(因此,如果将“file_nbr_1”与“file_23”进行比较,则不会比较字符串的每个部分,而只是进行常规字符串比较在完整的字符串上):

 char[] splitChars = new char[] { '_' }; string[] strings = new[] { "file_1", "file_8", "file_11", "file_2" }; Array.Sort(strings, delegate(string x, string y) { // split the strings into arrays on each '_' character string[] xValues = x.Split(splitChars); string[] yValues = y.Split(splitChars); // if the arrays are of different lengths, just //make a regular string comparison on the full values if (xValues.Length != yValues.Length) { return x.CompareTo(y); } // So, the arrays are of equal length, compare each element for (int i = 0; i < xValues.Length; i++) { if (i == xValues.Length - 1) { // we are looking at the last element of the arrays // first, try to parse the values as ints int xInt = 0; int yInt = 0; if (int.TryParse(xValues[i], out xInt) && int.TryParse(yValues[i], out yInt)) { // if parsing the values as ints was successful // for both values, make a numeric comparison // and return the result return xInt.CompareTo(yInt); } } if (string.Compare(xValues[i], yValues[i], StringComparison.InvariantCultureIgnoreCase) != 0) { break; } } return x.CompareTo(y); });