我有一个需要知道的集合不能为空或只包含一个项目代码。
在一般情况下,我想形式的扩展:
bool collectionHasAtLeast2Items = collection.AtLeast(2);
我可以很容易地编写扩展,列举了收集和增加一个索引,直到我打的请求的大小,或元素的跑出来,但有一些已经在LINQ框架,做到这一点? 我的想法(在什么来找我,顺序)::
bool collectionHasAtLeast2Items = collection.Take(2).Count() == 2;
要么
bool collectionHasAtLeast2Items = collection.Take(2).ToList().Count == 2;
这似乎工作,虽然采取更多的元素比集合行为中包含未定义(在文档中) Enumerable.Take方法 ,但是,它似乎做一个可以预料到的。
这不是最有效的解决方案,无论是列举曾采取的元素,然后再枚举算来,这是不必要的,或列举一次采取的元素,那么为了获取计数属性是不枚举构建列表-y,因为我其实不愿意列表。
这不是漂亮,我总是得把两个说法,一是以“X”,然后选中我实际收到的“X”,它取决于无证行为。
或许我可以使用:
bool collectionHasAtLeast2Items = collection.ElementAtOrDefault(2) != null;
然而,这不是语义清晰。 也许最好的是包装与一个方法名,这意味着我想要什么。 我假设,这将是有效的,我还没有反映在代码。
一些其他的想法是使用Last()
但我明确不想通过整个集合枚举。
或者,也许Skip(2).Any()
又不能完全语义明显,但比ElementAtOrDefault(2) != null
,但我想他们产生同样的结果?
有什么想法吗?
public static bool AtLeast<T>(this IEnumerable<T> source, int count)
{
// Optimization for ICollection<T>
var genericCollection = source as ICollection<T>;
if (genericCollection != null)
return genericCollection.Count >= count;
// Optimization for ICollection
var collection = source as ICollection;
if (collection != null)
return collection.Count >= count;
// General case
using (var en = source.GetEnumerator())
{
int n = 0;
while (n < count && en.MoveNext()) n++;
return n == count;
}
}
您可以使用Count() >= 2
,如果你序列实现ICollection
?
幕后, Enumerable.Count()
扩展方法检查确实下环的序列实现ICollection
。 如果它确实, Count
属性返回,所以目标性能应该是O(1)。
因此((IEnumerable<T>)((ICollection)sequence)).Count() >= x
还应具有O(1)。
你可以使用Count
,但是如果性能是一个问题,你将与更好Take
。
bool atLeastX = collection.Take(x).Count() == x;
由于Take
(我相信)使用延迟执行,那就只能去通过收集一次。
abatishchev提到Count
为O(1) ICollection
,所以你可以做这样的事情,并获得两全其美。
IEnumerable<int> col;
// set col
int x;
// set x
bool atLeastX;
if (col is ICollection<int>)
{
atLeastX = col.Count() >= x;
}
else
{
atLeastX = col.Take(x).Count() == x;
}
你也可以使用Skip/Any
,其实我敢打赌,这将是速度甚至比Take/Count
。
文章来源: Is there a LINQ extension or (a sensible/efficient set of LINQ entensions) that determine whether a collection has at least 'x' elements?