- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
这是对这个优秀问题的跟进 C# Sort and OrderBy comparison .我将使用相同的示例:
List<Person> persons = new List<Person>();
persons.Add(new Person("P005", "Janson"));
persons.Add(new Person("P002", "Aravind"));
persons.Add(new Person("P007", "Kazhal"));
争论的方法是:
persons.Sort((p1, p2) => string.Compare(p1.Name, p2.Name, true));
//and
persons.OrderBy(n => n.Name);
首先让我说,我知道没有任何显着的性能差异需要担心。但我很想知道为什么 OrderBy
表现比Sort
好得多.我正在使用@phoog 在原始问题中发布的答案。
private void button1_Click(object sender, EventArgs e)
{
IEnumerable<Person> people;
BenchMark(persons => persons.Sort((p1, p2) => string.Compare(p1.Name, p2.Name, true)));
BenchMark(persons => people = persons.OrderBy(n => n.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 static void BenchMark(Action<List<Person>> action)
{
List<Person> persons = new List<Person>();
for (int i = 0; i < 10000; i++)
{
persons.Add(new Person("P" + i.ToString(), RandomString(5, true)));
}
List<Person> unsortedPersons = new List<Person>(persons);
Stopwatch watch = new Stopwatch();
for (int i = 0; i < 100; i++)
{
watch.Start();
action(persons);
watch.Stop();
persons.Clear();
persons.AddRange(unsortedPersons);
}
MessageBox.Show(watch.Elapsed.TotalMilliseconds.ToString());
}
结果:
Sort() => 3500 ~ 5000 ms
OrderBy() => 0.2 ~ 1.5 ms
尽管我最初测试的列表较小时差异也很大,但一旦集合的大小增加,差异就会变得越来越明显。可能是我遗漏了一些理解 .NET 集合的关键,但我的想法是因为 Sort
作用于现有的 List<T>
,与 OrderBy
相比,它在处理过程中的开销(如果有的话)应该更小它作用于相同的 List<T>
(在我们的例子中是 persons
)但必须返回另一个集合 IOrderedEnumerable<T>
.但还是OrderBy
表现要好得多。 List<T>
与 IEnumerable<T>
相比可能会有一定的开销类型,但是 Sort
无论如何都对现有列表起作用!此外,我很高兴看到 Linq
方法比现有的 .NET 方法工作得更快。
原题所有答案对比Sort
反对OrderBy.ToList
我相信这会有一些开销,因此或多或少地表现相同。
实现差异可能是什么?
编辑: 好的,我学到了一些新东西。这是我确认延迟执行的方式。
private void button1_Click(object sender, EventArgs e)
{
BenchMark(persons =>
{
persons.Sort((p1, p2) => string.Compare(p1.Name, p2.Name, true));
foreach (var item in persons)
{
break;
}
});
BenchMark(persons =>
{
IEnumerable<Person> people = persons.OrderBy(n => n.Name);
foreach (var item in people)
{
break;
}
});
}
Sort
在 4000 - 5000 毫秒内运行 OrderBy
运行刚好超过 5000 毫秒。所以我的结论确实是错误的。一旦我开始列举这些收藏品,他们俩的表现就差不多了。我更喜欢 OrderBy
的语法任何时候:)
编辑 2: 我刚刚发现这与 this one 完全相同.但这里有一个 more interesting question about deferred execution in general虽然不是完全订购。
最佳答案
在这种情况下,OrderBy
速度要快得多,因为您实际上并没有执行它。
在您枚举结果之前,查询是延迟的,因此它从未实际进行排序。在您实际枚举结果之前,IOrderedEnumerable<T>
不处理输入并进行任何形式的排序。
尝试将基准更改为:
BenchMark(persons => people = persons.OrderBy(n => n.Name).Count());
Count()
调用将强制实际发生排序(因为它需要枚举 IOrderedEnumerable<T>
来生成计数),这应该会显着平衡您的时间。
大多数 LINQ 扩展方法都是这样工作的——直到您枚举它们(通过 Count()
、调用 ToList()
或只是在普通的 foreach
循环中使用它们,等等),它们的影响可以忽略不计,因为它们不' 实际上直接做任何事情,而不是构建可枚举的。其他基准与 OrderBy(...).ToList()
比较的原因是添加ToList()
强制 OrderBy
完全执行并实际排序结果。
关于c# - 为什么返回 IOrderedEnumerable<T> 的 OrderBy 比 Sort 快得多?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13181498/
我喜欢防御性编程。 我讨厌异常抛出,但这不是我的问题的主题。 我对 linQ 进行了扩展,以便能够使用列名执行订单 public static IEnumerable OrderBy(
是否应该将 IOrderedEnumerable 用作纯粹用于语义值的返回类型? 例如,在表示层消费模型时,我们如何知道集合是需要排序还是已经排序? 如果存储库使用 ORDER BY 子句包装存储过程
我这样排序字典: var sortedListOfNodes = _nodeDictionary.Values.OrderBy((n) => n.Time); 然后我选择了一个元素: var sele
我有一个 IOrderedEnumerable> (IGrouping 中的值与问题无关,因此用 var 抽象)。我有一个 List包含用作 IGrouping 键的字符串.我希望能够重新订购 IOr
在 C# 中,使用 Select() 投影 IOrderedEnumerable 的元素是否会保留元素顺序? 如果是这样,它为什么会返回一个IEnumerable,而不是一个IOrderedEnume
我想实现一些不同的算法来练习,只是为了看看我到底有多糟糕,然后变得更好:p 无论如何,我想我会尝试使用 IEnumerable和 IOrderedEnumerable和其他 .Net 集合类型只是为了
是否可以返回 IOrderedEnumerable来自不使用 OrderBy 的方法或 OrderByDescending IEnumerable 上的方法? 我猜也许不是……但是……也许我错了? 原
我想做的,简短的版本: var source = new[]{2,4,6,1,9}.OrderBy(x=>x); int count = source.Count; // source) {
有谁知道 LINQ 库(或公开可用的实用程序库)中是否有任何内置功能可用于 IOrderedEnumerable 上的优化操作,而不是 IEnumerable ? 例如,理论上,Contains()当
调用 AsQueryable()在 IOrderedEnumerable 上在 IEnumerable 上调用扩展方法并返回 IQueryable而不是 IOrderedQueryable . 这对我
我已经简化了这个问题。我有一个有序的 IEnumerable,我想知道为什么应用 where 过滤器可以取消对象的顺序 这不会编译,但它应该有潜力 IOrderedEnumerable tmp = n
我想在插入我的数据库之前对一些随机整数的顺序进行排序。 if (integerList.Direction.Equals("ascending")) { integerList.Integer
我目前遇到一个问题,我从以下方法中得到了 NullReferenceException: public void LoadValueXML() { XDocument
这个问题在这里已经有了答案: Is it possible to turn an IEnumerable into an IOrderedEnumerable without using Order
我想了解 ThenBy 在 .Net 中的工作原理。 (我知道怎么用,就是不明白微软是怎么实现的!) 根据文档,string_list.OrderBy(Function (x) x.length).T
string[] fruits = { "grape", "passionfruit", "banana", "mango", "orange",
我是这样写的: using System;using System.Linq; static class MyExtensions { public static IEnumerable In
如果你去这里:The IOrderedEnumerableDocs然后单击 .Contains() 方法,然后它会将您带到此处:the generalised Enumerable.Contains(
假设我有一个 IEnumerable 日期,我想获取一个范围内的日期。 Linq 和 IOrderedEnumerable 是否足够智能以实现选择更快算法的能力,因为现在日期已排序。 考虑一下: IO
我在使用以下代码时遇到了意想不到的问题。 List items = new List(); items = items.OrderBy(item => item); 此代码产生错误: Cannot i
我是一名优秀的程序员,十分优秀!