Early return when an Enumerable has more then X elements in Linq
LINQ中最有效的编写方法是什么:
return enumerable.Count() > x;
我至少在寻找一种解决方案:
- 不包括计算整个可枚举的。
- 最好是标准.NET LINQ。
- 应该在不同的提供者上工作。
请注意,enumerable.Any()在0以上的情况下工作得很好,但我正在寻找一个检查多于x的解决方案。
例子:
想象一个使用yield return构建的非常大的可枚举的。
- 嗯为什么下载?
- See this answer:stackoverflow.com/A/169699/96113
- 哈比卜,谢谢你的回答。在本案中,特别是在另一个案件中,评估了这一点。任何一部作品对大个子来说都是很好的。但如何比爱德华大?
- 我不确定还有其他办法可以做同样的事情。
- 好计数整个清单,你在x之后就知道了。
- Doessarily不需要调查整个收集。Stackoverflow.com/questions/168901/…
- 简单的,简单的法国电力公司
- 哈比卜,谢谢你的回答。它不需要调查整个收藏,但当我进入平原代码(I.E.Not within a linq to SQL)时,它会发生。
- Count性能与Count()方法没有任何差别。See stackoverflow.com/questions/4098186/…
- 我给我的问题添加了一个例子,让它更加清晰。
- 下载选民能解释更多吗?主要观点因为我喜欢一个简单的答案,或是在其他的线路供应商上工作?我想下面有一些混凝土的答案很有道理。
- 这个问题不是基于意见的。它有一套非常具体的要求和一个可接受的答案。这实际上是一个有兴趣的链接优化问题。
简单点怎么样:
1
| return enumerable.Skip(x).Any(); |
我想这就是你要找的。
- 这将枚举Count()不会枚举的集合。
- 好点。所以,如果您真的想让它对所有情况都有效,这意味着您需要首先进行一个自定义检查,如果它是一个IList?…所以我猜你是朝着编写自己的扩展方法的方向发展的吧?
- @Dirkboer在技术上可以检查ICollection,因为这是Count的定义,但是是的。注意,Enumerable.Count()正是这样做的。:)
- @Dirkboer是的,标准用例最有效的解决方案是检查ICollection,并首先使用count属性进行比较,因为它通常是o(1)。看看我的答案。
- 除了它仍然会在非查询上下文中枚举所有对象,@dstanley:)我感觉Mike Z的答案将是最接近的。
- @D Stanley是的,但也有相反的做法:当使用yield returnCount()时,将枚举整个序列,而Skip(x).Any()将只枚举第一个x元素:)
- @dirkboor甚至在内存中枚举也比返回一个Count属性慢,该属性可能在不需要实际枚举的情况下可用。
- @如果基础类型实现ICollection并具有预先计算的Count属性(如List或Array,则pwa不会枚举。
- @德斯坦利:就像普华斯所说的:埃多克斯1〔0〕。它不实现count()属性:)这样甚至可能遇到无限个可枚举项。
没有内置的LINQ方法可以提供最有效的解决方案。基本上,您需要检查IEnumerable是否具有count属性(通过ICollection),如果没有枚举它。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| public static class MoreEnumerable
{
public static bool HasAtLeast <T >(this IEnumerable <T > source, int count )
{
if (source is ICollection <T >)
{
return ((ICollection <T >)source ).Count > count ;
}
else if (source is ICollection )
{
return ((ICollection )source ).Count > count ;
}
return source .Skip(count ).Any();
}
} |
- 您可以使用take或skip
- @Luisfilipe-true主体可以使用take或skip,但重要的是,如果首先检查ICollection,性能会更好。
如果你只想用LINQ,我会用
1
| enumerable.Take(x).Count() == x |
尽管我更喜欢Selman22方法
我想你想要这样的东西:
1 2 3 4 5 6 7 8 9 10 11 12 13
| public static bool LazyCount<T>(this IEnumerable<T> source, int count)
{
var enumerator = source.GetEnumerator();
int i = 0;
while(enumerator.MoveNext())
{
i++;
if(i > count) return true;
}
return false;
} |
用法如下:
1
| return enumerable.LazyCount(x); |
注意:我不擅长命名,但您应该了解这个想法,您可以根据自己的喜好修改它。
What is the most performant (and beautiful) way in Linq to write:
return enumerable.Count() > x;
只是有什么问题:
1
| return enumerable.Count() > x; |
?
如果实际类型的enumerable也实现了ICollection,那么它只返回ICollection.Count,这通常是O(1)操作。对于IQueryable,大多数查询提供者都会将其转换为SELECT COUNT(*) FROM ...,这几乎是您所能得到的最快速度。
因此,与Count相比,执行性能更好的边缘案例相对较少;可能很少有足够多的案例试图为它们编写代码会适得其反。
- 它实际上更像是一个理论问题,而不是一个实际问题,但我添加了一个适当的例子。即一种非常大的yield return方法。
如果你想知道你是否有5个以上的孩子,你可以做以下的事情
enumerable.Take(6).Count() == 6