上下文:
我有一个numbers
类型的变量。
我想看看数字是否按升序排列。
算法
所以我得到了第一个元素,将它存储在IEnumerable<int>
中,并想对照下一个后续的数字来检查它。
// 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;
问题
我正在使用
prev
设置prev
的值,并跳过numbers.FirstOrDefault()
中的一个元素(numbers.Skip(1))从下一个元素开始。所以对于下面的代码,
numbers.FirstOrDefault()
numbers.Skip(1)
我是否将
foreach
枚举两次o(2n)?意思是迭代整个列表?-或者-
还是O(N)吗?(o(1)
numbers
的恒定时间+o(n)FirstOrDefault
) 最佳答案
有点微妙。Enumerable.FirstOrDefault
不会枚举整个序列,因为这样做毫无意义以下是the implementation:
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);
}
如果底层序列是
IList<T>
,则获得优化版本,否则将启动枚举。现在假设您的
IEnumerable<T>
实际上是一个表示数据库查询的实体框架IQueryable<T>
这意味着您的代码仍将执行查询两次。最好避免根据经验多次枚举
IEnumerable<T>
序列。如果知道枚举序列很便宜,则应使用更具描述性的类型,如ICollection<T>
或IReadOnlyCollection<T>
。关于c# - LINQ First/FirstOrDefault是否对整个可枚举进行迭代?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/47535487/