3 回答

TA貢獻1890條經驗 獲得超9個贊
保證非常非常少,但有一些優化:
使用索引訪問擴展方法,比如
ElementAt
,Skip
,Last
或者LastOrDefault
,將檢查底層式工具與否IList<T>
,讓你得到O(1)訪問,而不是O(N)。該
Count
方法檢查ICollection
實現,以便該操作是O(1)而不是O(N)。Distinct
,GroupBy
Join
我相信set-aggregation方法(Union
,Intersect
和Except
)也使用散列,所以它們應該接近O(N)而不是O(N2)。Contains
檢查ICollection
實現,因此如果底層集合也是O(1),它可能是O(1),例如aHashSet<T>
,但這取決于實際的數據結構,并且不能保證。散列集覆蓋了該Contains
方法,這就是它們為O(1)的原因。OrderBy
方法使用穩定的快速排序,因此它們是O(N log N)平均情況。
我認為這涵蓋了大多數(如果不是全部)內置擴展方法。實際保證很少; Linq本身將嘗試利用高效的數據結構,但編寫可能效率低下的代碼并不是免費的。

TA貢獻1804條經驗 獲得超8個贊
我早就知道如果枚舉是一個.Count()
返回。.Count
IList
但是我總是有點疲憊有關Set操作的運行時間復雜度:.Intersect()
,.Except()
,.Union()
。
這是針對.Intersect()
(評論我的)反編譯的BCL(.NET 4.0 / 4.5)實現:
private static IEnumerable<TSource> IntersectIterator<TSource>(IEnumerable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer){ Set<TSource> set = new Set<TSource>(comparer); foreach (TSource source in second) // O(M) set.Add(source); // O(1) foreach (TSource source in first) // O(N) { if (set.Remove(source)) // O(1) yield return source; }}
結論:
性能是O(M + N)
當集合已經設置時,實現不會占用優勢。(它可能不一定是直截了當的,因為使用過的也需要匹配。)
IEqualityComparer<T>
為了完整起見,這里都為實現.Union()
和.Except()
。
擾流板警報:它們也具有O(N + M) 復雜度。
private static IEnumerable<TSource> UnionIterator<TSource>(IEnumerable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer){ Set<TSource> set = new Set<TSource>(comparer); foreach (TSource source in first) { if (set.Add(source)) yield return source; } foreach (TSource source in second) { if (set.Add(source)) yield return source; }}private static IEnumerable<TSource> ExceptIterator<TSource>(IEnumerable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer){ Set<TSource> set = new Set<TSource>(comparer); foreach (TSource source in second) set.Add(source); foreach (TSource source in first) { if (set.Add(source)) yield return source; }}

TA貢獻1796條經驗 獲得超4個贊
所有你能真正依賴的是,Enumerable方法是針對一般情況編寫的,不會使用樸素算法??赡苡械谌降臇|西(博客等)描述了實際使用的算法,但這些并不是官方的,也不是STL算法所保證的。
為了說明,這里是Enumerable.Count
來自System.Core 的反映源代碼(由ILSpy提供):
// System.Linq.Enumerablepublic static int Count<TSource>(this IEnumerable<TSource> source){ checked { if (source == null) { throw Error.ArgumentNull("source"); } ICollection<TSource> collection = source as ICollection<TSource>; if (collection != null) { return collection.Count; } ICollection collection2 = source as ICollection; if (collection2 != null) { return collection2.Count; } int num = 0; using (IEnumerator<TSource> enumerator = source.GetEnumerator()) { while (enumerator.MoveNext()) { num++; } } return num; }}
正如您所看到的,它需要付出一些努力來避免簡單地枚舉每個元素的天真解決方案。
- 3 回答
- 0 關注
- 788 瀏覽
添加回答
舉報