C#sorting和OrderBy比较

我可以使用Sort或OrderBy对列表进行sorting。 哪一个更快? 两个工作在相同的algorithm?

List<Person> persons = new List<Person>(); persons.Add(new Person("P005", "Janson")); persons.Add(new Person("P002", "Aravind")); persons.Add(new Person("P007", "Kazhal")); 

1。

 persons.Sort((p1,p2)=>string.Compare(p1.Name,p2.Name,true)); 

2。

 var query = persons.OrderBy(n => n.Name, new NameComparer()); class NameComparer : IComparer<string> { public int Compare(string x,string y) { return string.Compare(x, y, true); } } 

为什么不测量它:

 class Program { class NameComparer : IComparer<string> { public int Compare(string x, string y) { return string.Compare(x, y, true); } } class Person { public Person(string id, string name) { Id = id; Name = name; } public string Id { get; set; } public string Name { get; set; } } static void Main() { List<Person> persons = new List<Person>(); persons.Add(new Person("P005", "Janson")); persons.Add(new Person("P002", "Aravind")); persons.Add(new Person("P007", "Kazhal")); Sort(persons); OrderBy(persons); const int COUNT = 1000000; Stopwatch watch = Stopwatch.StartNew(); for (int i = 0; i < COUNT; i++) { Sort(persons); } watch.Stop(); Console.WriteLine("Sort: {0}ms", watch.ElapsedMilliseconds); watch = Stopwatch.StartNew(); for (int i = 0; i < COUNT; i++) { OrderBy(persons); } watch.Stop(); Console.WriteLine("OrderBy: {0}ms", watch.ElapsedMilliseconds); } static void Sort(List<Person> list) { list.Sort((p1, p2) => string.Compare(p1.Name, p2.Name, true)); } static void OrderBy(List<Person> list) { var result = list.OrderBy(n => n.Name, new NameComparer()).ToArray(); } } 

在我的电脑上,当在发布模式下编译时,

 Sort: 1162ms OrderBy: 1269ms 

更新:

正如@Stefan所build议的那样,这里是对一个大列表sorting的结果:

 List<Person> persons = new List<Person>(); for (int i = 0; i < 100000; i++) { persons.Add(new Person("P" + i.ToString(), "Janson" + i.ToString())); } Sort(persons); OrderBy(persons); const int COUNT = 30; Stopwatch watch = Stopwatch.StartNew(); for (int i = 0; i < COUNT; i++) { Sort(persons); } watch.Stop(); Console.WriteLine("Sort: {0}ms", watch.ElapsedMilliseconds); watch = Stopwatch.StartNew(); for (int i = 0; i < COUNT; i++) { OrderBy(persons); } watch.Stop(); Console.WriteLine("OrderBy: {0}ms", watch.ElapsedMilliseconds); 

打印:

 Sort: 8965ms OrderBy: 8460ms 

在这种情况下,它看起来像OrderBy执行得更好。


UPDATE2:

并使用随机名称:

 List<Person> persons = new List<Person>(); for (int i = 0; i < 100000; i++) { persons.Add(new Person("P" + i.ToString(), RandomString(5, true))); } 

哪里:

 private static Random randomSeed = new Random(); public static string RandomString(int size, bool lowerCase) { var sb = new StringBuilder(size); int start = (lowerCase) ? 97 : 65; for (int i = 0; i < size; i++) { sb.Append((char)(26 * randomSeed.NextDouble() + start)); } return sb.ToString(); } 

产量:

 Sort: 8968ms OrderBy: 8728ms 

Still OrderBy更快

不,他们不是一样的algorithm。 对于初学者来说,LINQ OrderBy被logging为稳定的 (例如,如果两个项目具有相同的Name ,它们将以其原始顺序出现)。

这也取决于你是否缓冲查询vs迭代几次(LINQ到对象,除非你缓冲结果,将按每个foreach重新sorting)。

对于OrderBy查询,我也会试图使用:

 OrderBy(n => n.Name, StringComparer.{yourchoice}IgnoreCase); 

(对于CurrentCultureOrdinalInvariantCulture {yourchoice} )。

List<T>.Sort

此方法使用Array.Sort,它使用QuickSortalgorithm。 这个实现执行不稳定的sorting; 也就是说,如果两个要素相同,他们的顺序可能不会被保留。 相反,稳定的sorting保留了相同元素的顺序。

Enumerable.OrderBy

这种方法执行稳定的sorting; 也就是说,如果两个元素的键相等,则元素的顺序被保留。 相比之下,不稳定的sorting不会保留具有相同键的元素的顺序。 分类; 也就是说,如果两个要素相同,他们的顺序可能不会被保留。 相反,稳定的sorting保留了相同元素的顺序。

Darin Dimitrov的回答显示,在面对已经sorting的input时, OrderByList.Sort略快。 我修改了他的代码,所以它重复sorting未sorting的数据, OrderBy在大多数情况下稍慢。

此外, OrderBytesting使用ToArray强制枚举Linq枚举器,但显然返回与inputtypes( List<Person> )不同的types( Person[] )。 因此,我使用ToList而不是ToArray重新运行testing,并得到了更大的区别:

 Sort: 25175ms OrderBy: 30259ms OrderByWithToList: 31458ms 

代码:

 using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text; class Program { class NameComparer : IComparer<string> { public int Compare(string x, string y) { return string.Compare(x, y, true); } } class Person { public Person(string id, string name) { Id = id; Name = name; } public string Id { get; set; } public string Name { get; set; } public override string ToString() { return Id + ": " + Name; } } private static Random randomSeed = new Random(); public static string RandomString(int size, bool lowerCase) { var sb = new StringBuilder(size); int start = (lowerCase) ? 97 : 65; for (int i = 0; i < size; i++) { sb.Append((char)(26 * randomSeed.NextDouble() + start)); } return sb.ToString(); } private class PersonList : List<Person> { public PersonList(IEnumerable<Person> persons) : base(persons) { } public PersonList() { } public override string ToString() { var names = Math.Min(Count, 5); var builder = new StringBuilder(); for (var i = 0; i < names; i++) builder.Append(this[i]).Append(", "); return builder.ToString(); } } static void Main() { var persons = new PersonList(); for (int i = 0; i < 100000; i++) { persons.Add(new Person("P" + i.ToString(), RandomString(5, true))); } var unsortedPersons = new PersonList(persons); const int COUNT = 30; Stopwatch watch = new Stopwatch(); for (int i = 0; i < COUNT; i++) { watch.Start(); Sort(persons); watch.Stop(); persons.Clear(); persons.AddRange(unsortedPersons); } Console.WriteLine("Sort: {0}ms", watch.ElapsedMilliseconds); watch = new Stopwatch(); for (int i = 0; i < COUNT; i++) { watch.Start(); OrderBy(persons); watch.Stop(); persons.Clear(); persons.AddRange(unsortedPersons); } Console.WriteLine("OrderBy: {0}ms", watch.ElapsedMilliseconds); watch = new Stopwatch(); for (int i = 0; i < COUNT; i++) { watch.Start(); OrderByWithToList(persons); watch.Stop(); persons.Clear(); persons.AddRange(unsortedPersons); } Console.WriteLine("OrderByWithToList: {0}ms", watch.ElapsedMilliseconds); } static void Sort(List<Person> list) { list.Sort((p1, p2) => string.Compare(p1.Name, p2.Name, true)); } static void OrderBy(List<Person> list) { var result = list.OrderBy(n => n.Name, new NameComparer()).ToArray(); } static void OrderByWithToList(List<Person> list) { var result = list.OrderBy(n => n.Name, new NameComparer()).ToList(); } } 

我认为重要的是要注意SortOrderBy之间的另一个区别:

假设存在一个Person.CalculateSalary()方法,这需要很多时间; 甚至可能比sorting大列表的操作还要多。

比较

 // Option 1 persons.Sort((p1, p2) => Compare(p1.CalculateSalary(), p2.CalculateSalary())); // Option 2 var query = persons.OrderBy(p => p.CalculateSalary()); 

选项2可能具有优越的性能,因为它只调用了CalculateSalary方法n次,而Sort选项可能调用CalculateSalary高达2 n log( n )次,这取决于sortingalgorithm的成功。

您应该计算OrderBy和Sort方法使用的algorithm的复杂性。 我记得QuickSort的复杂度是n(log n),其中n是数组的长度。

我也search了orderby's,但是我甚至在msdn库中也找不到任何信息。 如果你没有任何相同的值和sorting相关的只有一个属性,我更喜欢使用Sort()方法; 如果不是,则使用OrderBy。