如何有效地确定IEnumerable是否包含多个元素?

时间:2013-06-24 23:46:29

标签: c# vb.net linq

给定初始化IEnumerable

IEnumerable<T> enumerable;

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

enumerable.Count() > 1

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

如果不枚举任何超过2个元素,我怎么能这样做?

4 个答案:

答案 0 :(得分:43)

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

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

我更喜欢第一个,因为检查Count() >= 1是否与Any()是一种常见方式,因此我觉得它更具可读性。

答案 1 :(得分:5)

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

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

它的IEnumerable<T> GetItems()方法应该以这种方式使用yield return

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

答案 2 :(得分:0)

@ Cameron-S的解决方案更简单但下面的效率更高。我基于Enumerable.Count()方法提出了这个问题。 Skip()将始终进行迭代而不是短路,以获得sourceICollection类型的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
}

答案 3 :(得分:-1)

我也有类似的需求,但是如果它只有一个值,则要从IEnumerable获取单个值。我为此做了一个扩展方法:

interface IQueryCasesAndMatches
{
    queryName?:string,
    caseCount?:number,
    statusAndMatches?:IMatchCountByStatus[]
}

要回答问题该集合仅包含1个项目吗?您可以这样做(在这种情况下,该集合包含引用类型):

  casesAndMatchesWidgetProps:{
            data: { QueryCasesAndMatches:[] }
}