vb.net 如何有效地确定 IEnumerable 是否具有多个元素?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17286950/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-17 14:01:44  来源:igfitidea点击:

How can I efficiently determine if an IEnumerable has more than one element?

c#vb.netlinq

提问by Sam

Given an initialised IEnumerable:

给定一个初始化的IEnumerable

IEnumerable<T> enumerable;

I would like to determine if it has more than one element. I think the most obvious way to do this is:

我想确定它是否有多个元素。我认为最明显的方法是:

enumerable.Count() > 1

However, I believe Count()enumerates the wholecollection, which is unnecessary for this use case. For example, if the collection contains a very large amount of elements or provided its data from an external source, this could be quite wasteful in terms of performance.

但是,我相信Count()枚举整个集合,这对于这个用例是不必要的。例如,如果集合包含大量元素或从外部源提供其数据,则在性能方面可能会非常浪费。

How can I do this without enumerating any more than 2 elements?

如何在不枚举超过 2 个元素的情况下执行此操作?

回答by Cameron S

You can test this in many ways by combining the extension methods in System.Linq... Two simple examples are below:

您可以通过组合 System.Linq 中的扩展方法以多种方式对此进行测试...下面是两个简单示例:

bool twoOrMore = enumerable.Skip(1).Any();
bool twoOrMoreOther = enumerable.Take(2).Count() == 2;

I prefer the first one since a common way to check whether Count() >= 1is with Any()and therefore I find it more readable.

我更喜欢第一个,因为这是检查是否Count() >= 1为 with的常用方法Any(),因此我发现它更具可读性。

回答by Andrevinsky

For the fun of it, call Next() twice, then get another IEnumerable.

为了好玩,调用 Next() 两次,然后获取另一个 IEnumerable。

Or, write a small wrapper class for this specific goal: EnumerablePrefetcher : IEnumerable<T>to try and fetch the specified amount of items upon initialization.

或者,为这个特定目标编写一个小的包装类:EnumerablePrefetcher : IEnumerable<T>在初始化时尝试获取指定数量的项目。

Its IEnumerable<T> GetItems()method should use yield return in this fashion

它的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;
}

回答by hIpPy

@Cameron-S's solution is simpler but below is more efficient. I came up with this based on Enumerable.Count()method. Skip()will always iterate and not short-circuit to get source's count for ICollectionor ICollection<T>type.

@Cameron-S 的解决方案更简单,但下面更有效。我想出了这个基于Enumerable.Count()方法。Skip()将始终迭代而不是短路以获取source's 计数ICollectionICollection<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;
                }
            }
        }
    }
    // returns true for source with 0 elements and count 0
    return num == count;
}