我可以使用Sort或OrderBy对列表进行排序。哪一个更快?两者都是一样的 算法
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);
}
}
答案 0 :(得分:112)
不,它们不是同一种算法。对于初学者,LINQ OrderBy
被记录为 stable (即如果两个项目具有相同的Name
,则它们将以原始顺序出现。)
它还取决于您是否缓冲查询与多次迭代(LINQ-to-Objects,除非您缓冲结果,将按foreach
重新排序。)
对于OrderBy
查询,我也很想使用:
OrderBy(n => n.Name, StringComparer.{yourchoice}IgnoreCase);
({yourchoice}
CurrentCulture
,Ordinal
或InvariantCulture
中的一个{{1}}。
此方法使用Array.Sort,其中 使用QuickSort算法。这个 实现执行不稳定 分类;也就是说,如果有两个元素 平等,他们的订单可能不是 保存。相比之下,稳定的排序 保留元素的顺序 是平等的。
此方法执行稳定排序;也就是说,如果两个元素的键相等,则保留元素的顺序。相反,不稳定的排序不会保留具有相同键的元素的顺序。 分类;也就是说,如果有两个元素 平等,他们的订单可能不是 保存。相比之下,稳定的排序 保留元素的顺序 是平等的。
答案 1 :(得分:85)
为什么不测量它:
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所建议的那样,对大型列表进行较少次排序的结果如下:
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更快
答案 2 :(得分:53)
Darin Dimitrov的回答显示,OrderBy
在面对已经排序的输入时比List.Sort
略快。我修改了他的代码,因此它重复排序未排序的数据,OrderBy
在大多数情况下稍慢。
此外,OrderBy
测试使用ToArray
强制枚举Linq枚举器,但这显然会返回一个与输入类型({{1)不同的类型(Person[]
) }})。因此,我使用List<Person>
而非ToList
重新进行了测试,并获得了更大的差异:
ToArray
代码:
Sort: 25175ms
OrderBy: 30259ms
OrderByWithToList: 31458ms
答案 3 :(得分:34)
我认为注意Sort
和OrderBy
之间的另一个区别非常重要:
假设存在Person.CalculateSalary()
方法,这需要花费大量时间;可能甚至超过排序大型列表的操作。
<强>比较强>
// Option 1
persons.Sort((p1, p2) => Compare(p1.CalculateSalary(), p2.CalculateSalary()));
// Option 2
var query = persons.OrderBy(p => p.CalculateSalary());
选项2 可能具有卓越的性能,因为它只调用CalculateSalary
方法 n 次,而Sort
选项可能会调用{{ 1}}最多2n log(n)次,具体取决于排序算法的成功。
答案 4 :(得分:7)
简而言之:
列表/数组Sort():
OrderBy / ThenBy():
x => x.Id
)。在排序之前,首先提取所有密钥。与使用Sort()和自定义比较器相比,这可能会导致更好的性能。 来源: MDSN,reference source和dotnet/coreclr存储库(GitHub)。
上面列出的某些语句基于当前的.NET Framework实现(4.7.2)。将来可能会改变。
答案 5 :(得分:0)
你应该计算OrderBy和Sort方法使用的算法的复杂性。 我记得QuickSort的复杂度为n(log n),其中n是数组的长度。
我也搜索了orderby,但即使在msdn库中也找不到任何信息。 如果你没有任何相同的值和排序只涉及一个属性,我更喜欢使用 Sort()方法;如果不是使用OrderBy。
答案 6 :(得分:-1)
我只想补充一下,orderby更有用。
为什么?
因为我可以这样做
Dim thisAccountBalances = account.DictOfBalances.Values.ToList
thisAccountBalances.ForEach(Sub(x) x.computeBalanceOtherFactors())
thisAccountBalances=thisAccountBalances.OrderBy(Function(x) x.TotalBalance).tolist
listOfBalances.AddRange(thisAccountBalances)
为何复杂的比较?只需根据字段进行排序。我在这里根据TotalBalance进行排序。
非常简单
我无法通过排序来做到这一点。我想知道为什么。订单执行得很好。
至于速度。它始终是O(n)