上下文:
我有一个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/

10-12 00:27
查看更多