46

给定一个初始化的IEnumerable

IEnumerable<T> enumerable;

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

enumerable.Count() > 1

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

如何在不枚举超过 2 个元素的情况下做到这一点?

4

4 回答 4

62

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

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

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

于 2013-06-24T23:49:31.480 回答
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;
}
于 2013-06-25T00:02:48.907 回答
2

@Cameron-S 的解决方案更简单,但下面更有效。我想出了这个基于Enumerable.Count()方法。Skip()将始终迭代而不是短路以获取source' 计数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;
}
于 2014-11-27T23:34:39.197 回答
-1

我有类似的需求,但是如果 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;
}

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

if (myList.OneOnlyOrDefault() == null)
{
    // list is either empty or contains more than one item
}
于 2020-11-06T18:57:07.437 回答