[英]Check if an IEnumerable has less than a certain number of items without causing any unnecessary evaluation?
Sometimes I expect a certain range of items and need to do some validation to ensure that I am within that range. 有时我希望有一定范围的项目,需要进行一些验证以确保我在该范围内。 The most obvious way to do this is to just compare the number of items in the collection with the range.
最明显的方法是将集合中的项目数与范围进行比较。
public static bool IsWithinRange<T>(this IEnumerable<T> enumerable, int max)
{
return enumerable.Count() <= max;
}
Although, my understanding is that the linq Count() method will evaluate the entire enumerable before returning a result. 虽然,我的理解是linq Count()方法将在返回结果之前评估整个可枚举。 Ideally I would only cause evaluation on the minimal number of items to get my result.
理想情况下,我只会对最小数量的项目进行评估以获得我的结果。
What would be the best way to ensure that an enumerable has less than a certain number of items without causing any unnecessary evaluation? 在不引起任何不必要评估的情况下,确保可枚举项目少于一定数量的最佳方法是什么?
Don't use Count()
, as you already know, the entire collection would have to be traversed in general. 不要使用
Count()
,正如您所知,整个集合必须遍历。
You can do this instead: 你可以这样做:
public static bool IsWithinRange<T>(this IEnumerable<T> enumerable, int max)
{
return !enumerable.Skip(max).Any();
}
Note you will still have to enumerate over the first max
items in the collection, that's unavoidable unless you try to make some assumptions about the underlying collection. 请注意,您仍然必须枚举集合中的第一个
max
项目,除非您尝试对基础集合做出一些假设,否则这是不可避免的。
To really optimize this further, you can check if the underlying type is an ICollection<>
or ICollection
in order to access the Count
property. 要进一步优化这一点,您可以检查基础类型是否为
ICollection<>
或ICollection
以访问Count
属性。 That way you don't have to enumerate over the items at all. 这样您就不必枚举项目了。 Otherwise fallback on enumerating the items.
否则在枚举项目时回退。
public static bool IsWithinRange<T>(this IEnumerable<T> enumerable, int max)
{
var asCollection = enumerable as System.Collections.ICollection;
if (asCollection != null) return asCollection.Count <= max;
var asGenericCollection = enumerable as ICollection<T>;
if (asGenericCollection != null) return asGenericCollection.Count <= max;
return !enumerable.Skip(max).Any();
}
Of course this isn't exactly free as you're doing additional checks, but it beats having to enumerate over the collection if at all possible, particularly if max
is large. 当然,这并不是完全免费的,因为你正在进行额外的检查,但是如果可能的话,它必须在集合上进行枚举,特别是如果
max
很大。
There are several different ways to do this. 有几种不同的方法可以做到这一点。 Perhaps the simplest is:
也许最简单的是:
public static bool IsWithinRange<T>(this IEnumerable<T> enumerable, int max)
{
return enumerable.Take(max+1).Count() <= max;
}
你可以将Count()
与Take()
结合起来。
return enumerable.Take(max + 1).Count() <= max;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.