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);
(对于CurrentCulture
, Ordinal
或InvariantCulture
{yourchoice}
)。
List<T>.Sort
此方法使用Array.Sort,它使用QuickSortalgorithm。 这个实现执行不稳定的sorting; 也就是说,如果两个要素相同,他们的顺序可能不会被保留。 相反,稳定的sorting保留了相同元素的顺序。
Enumerable.OrderBy
这种方法执行稳定的sorting; 也就是说,如果两个元素的键相等,则元素的顺序被保留。 相比之下,不稳定的sorting不会保留具有相同键的元素的顺序。 分类; 也就是说,如果两个要素相同,他们的顺序可能不会被保留。 相反,稳定的sorting保留了相同元素的顺序。
Darin Dimitrov的回答显示,在面对已经sorting的input时, OrderBy
比List.Sort
略快。 我修改了他的代码,所以它重复sorting未sorting的数据, OrderBy
在大多数情况下稍慢。
此外, OrderBy
testing使用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(); } }
我认为重要的是要注意Sort
和OrderBy
之间的另一个区别:
假设存在一个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。