C# LINQ First/FirstOrDefault是否迭代整个可枚举项?
上下文: 我有一个类型为IEnumerable的变量C# LINQ First/FirstOrDefault是否迭代整个可枚举项?,c#,algorithm,linq,big-o,C#,Algorithm,Linq,Big O,上下文: 我有一个类型为IEnumerable的变量numbers 我想检查数字是否按升序排列 算法 因此,我得到了第一个元素,将其存储在prev中,并希望对照接下来的数字进行检查 // numbers can contain "10, 20, 60, 50" IEnumerable<int> numbers = TraverseInOrder(root); int prev = numbers.FirstOrDefault(); foreach (var curr in numbe
numbers
我想检查数字是否按升序排列 算法 因此,我得到了第一个元素,将其存储在
prev
中,并希望对照接下来的数字进行检查
// numbers can contain "10, 20, 60, 50"
IEnumerable<int> numbers = TraverseInOrder(root);
int prev = numbers.FirstOrDefault();
foreach (var curr in numbers.Skip(1))
{
if (curr < prev) return false;
prev = curr;
}
return true;
我是否将数字枚举两次O(2N)?意思是迭代整个列表?
-或-
还是O(N)吗?(O(1)对于FirstOrDefault
+O(N)对于Skip(1)
)这有点微妙
Enumerable.FirstOrDefault
不会枚举整个序列,因为这样做没有意义。这是:
publicstatictsourcefirstOrdefault(此IEnumerable源代码){
if(source==null)抛出错误.ArgumentNull(“source”);
IList list=源作为IList;
如果(列表!=null){
如果(list.Count>0)返回列表[0];
}
否则{
使用(IEnumerator e=source.GetEnumerator()){
如果(e.MoveNext())返回e.Current;
}
}
返回默认值(TSource);
}
如果基础序列是IList
,则会得到优化版本,否则将启动枚举
现在假设您的IEnumerable
实际上是一个实体框架IQueryable
,它表示一个数据库查询。这意味着您的代码仍将执行两次查询
最好避免根据经验多次枚举IEnumerable
序列。如果您知道枚举序列很便宜,那么应该使用更具描述性的类型,如ICollection
或IReadOnlyCollection
FirstOrDefault()
不会迭代整个集合
只要做:
var moreNumbers = numbers.ToList();
// ...stuff with the list.
我会巧妙地改变你的技巧,这样你就不需要知道了(尽管其他答案都是针对你特别要求的):
IEnumerable numbers=traverseInoder(根);
int prev=0;
bool first=true;
foreach(数值形式的var curr)
{
如果(!first&&curr
现在您知道了(即使没有阅读文档!)这段代码只会对可枚举项迭代一次。或者最好看看源代码@Sung you's correct,上面有很多不好的问题,因此不应该问,因为阅读文档可以轻松地回答这些问题。这并不意味着可以通过阅读文档来提出一些简单的问题。因此,这不是一个提问的地方,因为您不必费心在文档中查找答案,也不必运行自己的代码来查看它的功能。或者只需int prev=int.MinValue
感谢这里的伟大提示@Damien_the_unsiver我也阅读了source.GetEnumerator()的源代码“将启动枚举”FirstOrDefault
将只到达第一个元素。感谢您的回答@Sung yes,但在数据库查询的示例中,您将只检索第一行,但仍将执行查询以到达该行。
public static TSource FirstOrDefault<TSource>(this IEnumerable<TSource> source) {
if (source == null) throw Error.ArgumentNull("source");
IList<TSource> list = source as IList<TSource>;
if (list != null) {
if (list.Count > 0) return list[0];
}
else {
using (IEnumerator<TSource> e = source.GetEnumerator()) {
if (e.MoveNext()) return e.Current;
}
}
return default(TSource);
}
var moreNumbers = numbers.ToList();
// ...stuff with the list.
IEnumerable<int> numbers = TraverseInOrder(root);
int prev = 0;
bool first = true;
foreach (var curr in numbers)
{
if (!first && curr < prev) return false;
prev = curr;
first = false;
}
return true;