简单的linq(到对象)查询的空间复杂性

时间:2010-08-08 19:41:46

标签: c# linq

我有;

var maxVal = l.TakeWhile(x=>x < val).Where(x=>Matches(x)).Max();

这需要多少空间? linq是否构建了上面Where()条件的列表,或者是Max()只是迭代IEnumerable跟踪当前的Max()是什么?

除了询问SO f

之外,我还能在哪里找到更多相关信息

4 个答案:

答案 0 :(得分:7)

我已经使用Reflector验证了Enumerable.TakeWhile,Enumerable.Where和Enumerable.Max中的每一个都在恒定空间中运行。因此,整个查询应该在恒定的空间中运行。 考虑到TakeWhile和Where在哪里使用延迟执行+流媒体,这并不奇怪。 Max不使用延迟执行,但只需要存储'max far'和源枚举器可枚举。

答案 1 :(得分:0)

根据Reflector Max()方法迭代可枚举。

  

除了询问SO f

之外,我还能在哪里找到更多相关信息

您可以使用Reflector查看任何.NET程序集的实现。

答案 2 :(得分:0)

Reflector是你的朋友。

特别是,您可以在Enumerable的{​​{1}}课程中查看Linq to Objects扩展方法。

以上是使用迭代,因此它们使用枚举器占用的任何空间 - 通常是O(1)。 Max()是O(1)空格。

但是,请记住,没有什么能阻止开发人员编写占用超过常量空间的枚举数。例如。遍历树可能需要O(log n)空间。这种情况例如是System.LinqSortedDictionary<K,V>

因此,它部分取决于代码中的SortedSet<K,V>

答案 3 :(得分:0)

由于显而易见的原因,Enumerable提供的唯一不会在常量空间中运行的东西是ToList()。

使用一些枚举,这是低效的,因为您已经具有高于常量的空间复杂度(通常在存储项目时为O(n))并且所讨论的集合提供了具有较低时间复杂度的机制。如果您自己创建这样的集合,那么提供您自己的Enumerable提供的扩展版本是有意义的。例如,如果你有一个固有排序的集合,你应该能够提供比O(n)复杂度更好的Min()和Max()(无论是O(1),O(ln)还是别的什么取决于保持排序的方式)。由于实例方法会覆盖扩展方法(在对象类型的表达式而不是实例类型上调用时),因此使用对象与编码器没有区别,您将提供更高的效率。