给予初始化IEnumerable
:如何有效地确定IEnumerable是否包含多个元素?
IEnumerable<T> enumerable;
我想确定它是否有一个以上的元素。我觉得最明显的方式做到这一点是:
enumerable.Count() > 1
不过,我相信Count()
枚举整个集合,这是不必要的这种使用情况。例如,如果集合包含非常大量的元素或从外部来源提供其数据,那么在性能方面可能会非常浪费。
如何在不枚举超过2个元素的情况下做到这一点?
给予初始化IEnumerable
:如何有效地确定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()
,因此我觉得它更具可读性。
这并不总是有效的,如果这是你丢失了数据的数据流跳过和/或拿走。此外,如果每次对可枚举进行操作时数据都在发生变化,这意味着您在完成此测试后对数据的评估可能会有所不同。 – devshorts
@devshorts但他只关心计数,而不是实际的数据。 –
@devshorts True。当然,如果需要,您可以将Take(2)结果保存为变量,但这不是问题中的要求。 –
为了好玩,调用Next()两次,然后获得另一个IEnumerable。
或者,为此特定目标编写一个小封装类:EnumerablePrefetcher : IEnumerable<T>
尝试在初始化时获取指定数量的项目。 @卡梅伦-S的解决方案是简单,但下面是更有效的
其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;
}
。我想出了这个基于Enumerable.Count()
的方法。 Skip()
将始终迭代并且不会短路,以获得source
的计数为ICollection
或ICollection<T>
类型。
/// <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;
}
}
}
}
return false; // < count
}
如果你必须指望它,那么做点什么,你最好强迫它评估一个列表或其他集合。 – devshorts
@devshorts,通过*计数*,你的意思是*取决于它的工作*或*使用'Count()'方法*? – Sam
我的意思是,如果你需要找到它上面有多少个元素,那么根据这个做一些事情,你可以评估它。 'Count'会评估一次,然后如果再次迭代,则必须重新评估一切。与其他'IEnumerable'方法相同,如'Take'或Skip'。这真的取决于数据是什么。 – devshorts