如何有效地确定IEnumerable是否包含多个元素
本文关键字:是否 包含多 元素 IEnumerable 有效地 | 更新日期: 2023-09-27 18:19:55
给定初始化的IEnumerable
:
IEnumerable<T> enumerable;
我想确定它是否有不止一个元素。我认为最明显的方法是:
enumerable.Count() > 1
但是,我认为Count()
枚举了整个集合,这对于本用例来说是不必要的。例如,如果集合包含大量元素,或者从外部源提供数据,那么在性能方面可能会非常浪费。
如何在不枚举任何超过2个元素的情况下完成此操作?
您可以通过结合System.Linq中的扩展方法以多种方式对此进行测试…下面是两个简单的示例:
bool twoOrMore = enumerable.Skip(1).Any();
bool twoOrMoreOther = enumerable.Take(2).Count() == 2;
我更喜欢第一个,因为检查Count() >= 1
是否与Any()
在一起是一种常见的方法,因此我觉得它更可读。
为了好玩,调用Next()两次,然后获取另一个IEnumerable。
或者,为这个特定目标编写一个小包装类:EnumerablePrefetcher : IEnumerable<T>
,尝试在初始化时获取指定数量的项。
它的IEnumerable<T> GetItems()
方法应该以这种方式使用收益回报
foreach (T item in prefetchedItems) // array of T, prefetched and decided if IEnumerable has at least n elements
{
yield return item;
}
foreach (T item in otherItems) // IEnumerable<T>
{
yield return item;
}
@Cameron-S的解决方案更简单,但下面的解决方案效率更高。我是在Enumerable.Count()
方法的基础上提出的。对于ICollection
或ICollection<T>
类型,Skip()
将始终迭代而不短路以获得source
的计数。
/// <summary>
/// Returns true if source has at least <paramref name="count"/> elements efficiently.
/// </summary>
/// <remarks>Based on int Enumerable.Count() method.</remarks>
public static bool HasCountOfAtLeast<TSource>(this IEnumerable<TSource> source, int count)
{
source.ThrowIfArgumentNull("source");
var collection = source as ICollection<TSource>;
if (collection != null)
{
return collection.Count >= count;
}
var collection2 = source as ICollection;
if (collection2 != null)
{
return collection2.Count >= count;
}
int num = 0;
checked
{
using (var enumerator = source.GetEnumerator())
{
while (enumerator.MoveNext())
{
num++;
if (num >= count)
{
return true;
}
}
}
}
// returns true for source with 0 elements and count 0
return num == count;
}
我也有类似的需求,但如果IEnumerable只有一个值,那么就从它获得一个值。我为它做了一个扩展方法:
public static S OneOnlyOrDefault<S>(this IEnumerable<S> items)
{
var rtn = default(S);
using (var en = items.GetEnumerator())
{
if (en.MoveNext())
{
rtn = en.Current;
}
if (en.MoveNext())
{
rtn = default(S);
}
}
return rtn;
}
要回答这个集合只包含一个项目吗你可以这样做(在这种情况下,集合包含引用类型):
if (myList.OneOnlyOrDefault() == null)
{
// list is either empty or contains more than one item
}