如何用C#排序字符串

我有一个类似的课程

public class KeyNamePair { public string Key {get;set;} public string Name{get;set;} } 

我的代码

 List list =new List(); list.Add("1", "Day 1"); list.Add("2", "Day 11"); list.Add("4", "Day 5"); list.Add("6", "Day 13"); 

如何对要显示的列表进行排序

 > "Day1", "Day5", "Day 11", "Day 13" 

为了?

我试过了

 var SortedList = source.OrderBy(x => x.Name).ToList(); return SortedList; 

这没有做任何改变

尝试以下方法:

 var SortedList = source.OrderBy(x=>int.Parse(x.Name.Split(' ')[1])).ToList(); return SortedList; 

如果数据是其他格式,它将无法工作,但它应该与您提供的格式一起使用。 您不能按字符串本身排序,因为字符串“13”<“5”

这有什么机会吗?

第1天第11天第13天第5天

这将是我所期待的。 OrderBy上存在重载,允许您指定排序方式。 正在发生的排序是一个字母数字排序,所以它正确的做法。 如果你做了……

第01天第11天第13天第05天

你会看到它正确排序。

我们可以通过PInvoking Windows API函数StrCmpLogicalW()完全欺骗这里,它在两个字符串之间进行自然的排序顺序比较。

然后我们可以使用内置的List.Sort()。 根本不需要涉及Linq:

 using System; using System.Collections.Generic; using System.Runtime.InteropServices; namespace Demo { class Program { [DllImport("shlwapi.dll", CharSet = CharSet.Unicode)] private static extern int StrCmpLogicalW(string lhs, string rhs); private void run() { var list = new List> { new KeyValuePair("1", "Day 1"), new KeyValuePair("2", "Day 11"), new KeyValuePair("4", "Day 5"), new KeyValuePair("6", "Day 13") }; list.Sort((lhs, rhs) => StrCmpLogicalW(lhs.Value, rhs.Value)); foreach (var keyValuePair in list) Console.WriteLine(keyValuePair); } static void Main(string[] args) { new Program().run(); } } } 

我假设您确实想要对“值”进行排序,而不是对“密钥”进行排序,并且您遇到的问题是字符串数字不按数字顺序排序。


编辑:应用Jim Tollan的想法,您可以创建一个扩展方法来隐藏PInvoke,如下所示:

 public static class ListExt { [DllImport("shlwapi.dll", CharSet = CharSet.Unicode)] private static extern int StrCmpLogicalW(string lhs, string rhs); // Version for lists of any type. public static void SortNatural(this List self, Func stringSelector) { self.Sort((lhs, rhs) => StrCmpLogicalW(stringSelector(lhs), stringSelector(rhs))); } // Simpler version for List public static void SortNatural(this List self) { self.Sort(StrCmpLogicalW); } } 

然后,对列表进行排序的行将如下所示:

 list.SortNatural(element => element.Value); 

这应该工作:

 list = list.OrderBy(kn => { var digits = kn.Name.Split().Last(); int num = int.MaxValue; if (digits.All(Char.IsDigit)) { num = int.Parse(new string(digits.ToArray())); } return num; }).ToList(); 

Side-Note:您还可以使用已经可用的KeyValuePair

我认为这不是一个好方法,但这项工作

 list.OrderBy(x => { return Int32.Parse(x.Name.Split(' ')[1]); }); 

你在这里遇到了一些问题:

  1. 您正在尝试对名称属性进行排序,该属性将“第1天”和“第11天”计为比“第1天”和“第2天”更紧密匹配
  2. 您可能更好地对Key进行排序(另外,我会创建键数字,而不是字符串,如果它只包含数值)。

这是我的修订版:

 public class KeyNamePair { public int Key { get; set; } public string Name { get; set; } } List list = new List { new KeyNamePair() {Key = 1, Name = "Day 1"}, new KeyNamePair() {Key = 4, Name = "Day 11"}, new KeyNamePair() {Key = 2, Name = "Day 5"}, new KeyNamePair() {Key = 6, Name = "Day 13"} }; var sortedList = list.Select(x => x).OrderBy(x => x.Key).ToList(); 

[编辑] – 我正在思考这样一个事实,即我认为重构阶级的逻辑和它的人口会更好,而不是试图合并一些可能在文化特定实施上失败的仲裁命令,如在这方面,字符串是众所周知的脆弱。

我相信你会对此感到高兴:)

 public class KeyNamePair : IComparable { public string Key { get; set; } public string Name { get; set; } public KeyNamePair(string key, string name) { this.Key = key; this.Name = name; } public int CompareTo(object obj) { var tmp = (KeyNamePair)obj; var newKey = int.Parse(tmp.Name.Split(' ')[1]); var oldKey = int.Parse(Name.Split(' ')[1]); if (oldKey > newKey) return (1); if (oldKey < newKey) return (-1); else return (0); } } List list = new List(); list.Add(new KeyNamePair("1", "Day 1")); list.Add(new KeyNamePair("2", "Day 11")); list.Add(new KeyNamePair("4", "Day 5")); list.Add(new KeyNamePair("6", "Day 13")); list.Sort(); foreach (var keyNamePair in list) { System.Console.Write(keyNamePair); }