c#linq orderby是string的数字(你不能将它们转换为int)

我想sorting的string数字的数组,我想他们sorting数字。

问题是我不能将数字转换为int

这里是代码:

string[] things= new string[] { "105", "101", "102", "103", "90" }; foreach (var thing in things.OrderBy(x => x)) { Console.WriteLine(thing); } 

输出:101,102,103,105,90

我想:90,101,102,103,105

编辑:输出不能是090,101,102 …

将代码示例更新为“事物”而不是“尺寸”。 数组可以是这样的:

 string[] things= new string[] { "paul", "bob", "lauren", "007", "90" }; 

这意味着它需要按照字母顺序和数字进行sorting:

007,90,鲍勃,劳伦,保罗

将自定义比较器传递给OrderBy。 Enumerable.OrderBy将让你指定你喜欢的任何比较器。

这是做到这一点的一种方法:

 void Main() { string[] things= new string[] { "paul", "bob", "lauren", "007", "90", "101"}; foreach (var thing in things.OrderBy(x => x, new SemiNumericComparer())) { Console.WriteLine(thing); } } public class SemiNumericComparer: IComparer<string> { public int Compare(string s1, string s2) { if (IsNumeric(s1) && IsNumeric(s2)) { if (Convert.ToInt32(s1) > Convert.ToInt32(s2)) return 1; if (Convert.ToInt32(s1) < Convert.ToInt32(s2)) return -1; if (Convert.ToInt32(s1) == Convert.ToInt32(s2)) return 0; } if (IsNumeric(s1) && !IsNumeric(s2)) return -1; if (!IsNumeric(s1) && IsNumeric(s2)) return 1; return string.Compare(s1, s2, true); } public static bool IsNumeric(object value) { try { int i = Convert.ToInt32(value.ToString()); return true; } catch (FormatException) { return false; } } } 

只需用零填充相同的长度:

 int maxlen = sizes.Max(x => x.Length); sizes.OrderBy(x => x.PadLeft(maxlen, '0')); 

那这个怎么样

 string[] sizes = new string[] { "105", "101", "102", "103", "90" }; var size = from x in sizes orderby x.Length, x select x; foreach (var p in size) { Console.WriteLine(p); } 

值是一个string

 List = List.OrderBy(c => c.Value.Length).ThenBy(c => c.Value).ToList(); 

作品

这似乎是一个奇怪的请求,值得一个奇怪的解决scheme:

 string[] sizes = new string[] { "105", "101", "102", "103", "90" }; foreach (var size in sizes.OrderBy(x => { double sum = 0; int position = 0; foreach (char c in x.ToCharArray().Reverse()) { sum += (c - 48) * (int)(Math.Pow(10,position)); position++; } return sum; })) { Console.WriteLine(size); } 

你说你不能将数字转换为int,因为数组可以包含无法转换为int的元素,但是在尝试时没有任何伤害:

 string[] things = new string[] { "105", "101", "102", "103", "90", "paul", "bob", "lauren", "007", "90" }; Array.Sort(things, CompareThings); foreach (var thing in things) Debug.WriteLine(thing); 

然后比较这样:

 private static int CompareThings(string x, string y) { int intX, intY; if (int.TryParse(x, out intX) && int.TryParse(y, out intY)) return intX.CompareTo(intY); return x.CompareTo(y); } 

输出:007,90,90,101,102,103,105,bob,lauren,paul

尝试这个

 sizes.OrderBy(x => Convert.ToInt32(x)).ToList<string>(); 

注意:这将有助于当所有的string转换为int …..

我想这将是更好,如果它在string中有一些数字。 希望它会有所帮助。

PS:我不确定性能或复杂的string值,但它的工作是这样的:

lorem ipsum
lorem ipsum 1
lorem ipsum 2
lorem ipsum 3

Lorem ipsum 20
Lorem ipsum 21

 public class SemiNumericComparer : IComparer<string> { public int Compare(string s1, string s2) { int s1r, s2r; var s1n = IsNumeric(s1, out s1r); var s2n = IsNumeric(s2, out s2r); if (s1n && s2n) return s1r - s2r; else if (s1n) return -1; else if (s2n) return 1; var num1 = Regex.Match(s1, @"\d+$"); var num2 = Regex.Match(s2, @"\d+$"); var onlyString1 = s1.Remove(num1.Index, num1.Length); var onlyString2 = s2.Remove(num2.Index, num2.Length); if (onlyString1 == onlyString2) { if (num1.Success && num2.Success) return Convert.ToInt32(num1.Value) - Convert.ToInt32(num2.Value); else if (num1.Success) return 1; else if (num2.Success) return -1; } return string.Compare(s1, s2, true); } public bool IsNumeric(string value, out int result) { return int.TryParse(value, out result); } } 

在Windows StrCmpLogicalW中有一个本地函数,它将比较string中的数字而不是字母。 做一个比较器来调用这个函数并且用它进行比较是很容易的。

 public class StrCmpLogicalComparer : Comparer<string> { [DllImport("Shlwapi.dll", CharSet = CharSet.Unicode)] private static extern int StrCmpLogicalW(string x, string y); public override int Compare(string x, string y) { return StrCmpLogicalW(x, y); } } 

它甚至适用于既有文本又有数字的string。 这是一个示例程序,它将显示默认sorting和StrCmpLogicalWsorting之间的StrCmpLogicalW

 class Program { static void Main() { List<string> items = new List<string>() { "Example1.txt", "Example2.txt", "Example3.txt", "Example4.txt", "Example5.txt", "Example6.txt", "Example7.txt", "Example8.txt", "Example9.txt", "Example10.txt", "Example11.txt", "Example12.txt", "Example13.txt", "Example14.txt", "Example15.txt", "Example16.txt", "Example17.txt", "Example18.txt", "Example19.txt", "Example20.txt" }; items.Sort(); foreach (var item in items) { Console.WriteLine(item); } Console.WriteLine(); items.Sort(new StrCmpLogicalComparer()); foreach (var item in items) { Console.WriteLine(item); } Console.ReadLine(); } } 

哪个输出

 Example1.txt Example10.txt Example11.txt Example12.txt Example13.txt Example14.txt Example15.txt Example16.txt Example17.txt Example18.txt Example19.txt Example2.txt Example20.txt Example3.txt Example4.txt Example5.txt Example6.txt Example7.txt Example8.txt Example9.txt Example1.txt Example2.txt Example3.txt Example4.txt Example5.txt Example6.txt Example7.txt Example8.txt Example9.txt Example10.txt Example11.txt Example12.txt Example13.txt Example14.txt Example15.txt Example16.txt Example17.txt Example18.txt Example19.txt Example20.txt 

尝试这个 :

 string[] things= new string[] { "105", "101", "102", "103", "90" }; int tmpNumber; foreach (var thing in (things.Where(xx => int.TryParse(xx, out tmpNumber)).OrderBy(xx => int.Parse(xx))).Concat(things.Where(xx => !int.TryParse(xx, out tmpNumber)).OrderBy(xx => xx))) { Console.WriteLine(thing); } 

本网站讨论字母数字sorting,将按逻辑意义sorting数字,而不是ASCII意义。 它也考虑到它周围的alpha:

http://www.dotnetperls.com/alphanumeric-sorting

例:

  • C:/TestB/333.jpg
  • 11
  • C:/TestB/33.jpg
  • 1
  • C:/TestA/111.jpg
  • 111F
  • C:/TestA/11.jpg
  • 2
  • C:/TestA/1.jpg
  • 111D
  • 22
  • 111Z
  • C:/TestB/03.jpg

  • 1
  • 2
  • 11
  • 22
  • 111D
  • 111F
  • 111Z
  • C:/TestA/1.jpg
  • C:/TestA/11.jpg
  • C:/TestA/111.jpg
  • C:/TestB/03.jpg
  • C:/TestB/33.jpg
  • C:/TestB/333.jpg

代码如下:

 class Program { static void Main(string[] args) { var arr = new string[] { "C:/TestB/333.jpg", "11", "C:/TestB/33.jpg", "1", "C:/TestA/111.jpg", "111F", "C:/TestA/11.jpg", "2", "C:/TestA/1.jpg", "111D", "22", "111Z", "C:/TestB/03.jpg" }; Array.Sort(arr, new AlphaNumericComparer()); foreach(var e in arr) { Console.WriteLine(e); } } } public class AlphaNumericComparer : IComparer { public int Compare(object x, object y) { string s1 = x as string; if (s1 == null) { return 0; } string s2 = y as string; if (s2 == null) { return 0; } int len1 = s1.Length; int len2 = s2.Length; int marker1 = 0; int marker2 = 0; // Walk through two the strings with two markers. while (marker1 < len1 && marker2 < len2) { char ch1 = s1[marker1]; char ch2 = s2[marker2]; // Some buffers we can build up characters in for each chunk. char[] space1 = new char[len1]; int loc1 = 0; char[] space2 = new char[len2]; int loc2 = 0; // Walk through all following characters that are digits or // characters in BOTH strings starting at the appropriate marker. // Collect char arrays. do { space1[loc1++] = ch1; marker1++; if (marker1 < len1) { ch1 = s1[marker1]; } else { break; } } while (char.IsDigit(ch1) == char.IsDigit(space1[0])); do { space2[loc2++] = ch2; marker2++; if (marker2 < len2) { ch2 = s2[marker2]; } else { break; } } while (char.IsDigit(ch2) == char.IsDigit(space2[0])); // If we have collected numbers, compare them numerically. // Otherwise, if we have strings, compare them alphabetically. string str1 = new string(space1); string str2 = new string(space2); int result; if (char.IsDigit(space1[0]) && char.IsDigit(space2[0])) { int thisNumericChunk = int.Parse(str1); int thatNumericChunk = int.Parse(str2); result = thisNumericChunk.CompareTo(thatNumericChunk); } else { result = str1.CompareTo(str2); } if (result != 0) { return result; } } return len1 - len2; } } 

Jeff Paulsen给出的答案是正确的,但Comprarer可以简化为:

 public class SemiNumericComparer: IComparer<string> { public int Compare(string s1, string s2) { if (IsNumeric(s1) && IsNumeric(s2)) return Convert.ToInt32(s1) - Convert.ToInt32(s2) if (IsNumeric(s1) && !IsNumeric(s2)) return -1; if (!IsNumeric(s1) && IsNumeric(s2)) return 1; return string.Compare(s1, s2, true); } public static bool IsNumeric(object value) { int result; return Int32.TryParse(value, out result); } } 

这是有效的,因为检查比较器结果的唯一方法是如果结果大于,小于或等于零。 人们可以简单地从另一个值中减去值,而不必处理返回值。

此外, IsNumeric方法不应该使用try block,并且可以受益于TryParse

对于那些不确定的人:这个比较器会对值进行sorting,所以非数字值总是附加到列表的末尾。 如果有人希望他们在开始的第二和第三if块必须交换。

 Try this out.. string[] things = new string[] { "paul", "bob", "lauren", "007", "90", "-10" }; List<int> num = new List<int>(); List<string> str = new List<string>(); for (int i = 0; i < things.Count(); i++) { int result; if (int.TryParse(things[i], out result)) { num.Add(result); } else { str.Add(things[i]); } } 

现在对列表进行sorting并将它们合并回来…

  var strsort = from s in str orderby s.Length select s; var numsort = from n in num orderby n select n; for (int i = 0; i < things.Count(); i++) { if(i < numsort.Count()) things[i] = numsort.ElementAt(i).ToString(); else things[i] = strsort.ElementAt(i - numsort.Count()); } 

我试图在这个有趣的问题上做出贡献…

即使这是一个老问题,我想提供一个解决scheme:

 string[] things= new string[] { "105", "101", "102", "103", "90" }; foreach (var thing in things.OrderBy(x => Int32.Parse(x) ) { Console.WriteLine(thing); } 

Woha很简单吧? :d

我的首选解决scheme(如果所有string都只是数字):

 // Order by numerical order: (Assertion: all things are numeric strings only) foreach (var thing in things.OrderBy(int.Parse)) { Console.Writeline(thing); } 
 public class Test { public void TestMethod() { List<string> buyersList = new List<string>() { "5", "10", "1", "str", "3", "string" }; List<string> soretedBuyersList = null; soretedBuyersList = new List<string>(SortedList(buyersList)); } public List<string> SortedList(List<string> unsoredList) { return unsoredList.OrderBy(o => o, new SortNumericComparer()).ToList(); } } public class SortNumericComparer : IComparer<string> { public int Compare(string x, string y) { int xInt = 0; int yInt = 0; int result = -1; if (!int.TryParse(x, out xInt)) { result = 1; } if(int.TryParse(y, out yInt)) { if(result == -1) { result = xInt - yInt; } } else if(result == 1) { result = string.Compare(x, y, true); } return result; } } 
 public class NaturalSort: IComparer<string> { [DllImport("shlwapi.dll", CharSet = CharSet.Unicode)] public static extern int StrCmpLogicalW(string x, string y); public int Compare(string x, string y) { return StrCmpLogicalW(x, y); } } 

arr = arr.OrderBy(x => x,new NaturalSort())。ToArray();

我需要它的原因是得到一个目录,其文件名以一个数字开头:

 public static FileInfo[] GetFiles(string path) { return new DirectoryInfo(path).GetFiles() .OrderBy(x => x.Name, new NaturalSort()) .ToArray(); }