kiml42
kiml42

Reputation: 660

What's the quickest way to check the size of an IEnumerable is greater than some given value?

I know that you can use enumerable.Any() instead of enumerable.Count() to check if the collection has anything in it efficiently.

Is there an equivalent to check the size is at least any larger size?

For example, how would I efficiently do enumerable.Count() > 3.

Upvotes: 0

Views: 1210

Answers (2)

Jon Skeet
Jon Skeet

Reputation: 1502746

The most efficient approach will unfortunately depend on the implementation. It's a leaky abstraction at that point.

If you're using a List<T> or similar, using Count() will be fastest. But for any lazily-evaluated sequence, that will evaluate the whole sequence.

For a lazily-evaluated sequence, using enumerable.Skip(3).Any() will be more efficient, because it can stop once it's found the fourth element. That's all you need to know about; you don't care about the actual size.

Using the Skip()/Any() approach will be slightly less efficient than using Count() for some collections - but could be much more efficient for large lazy sequences. (It will also work even for infinite sequences, which Count() wouldn't.)

The difference in efficiency for lists will depend on how many items you're skipping, of course - if you need to see whether there are "at least a million" items then using Count() would be much more efficient for a list.

Sorry not to have an easy answer for you. If you really need this to be optimal in every case, you could perform the same kinds of optimization that the Count() method does. Something like this:

// FIXME: This name is horrible! Note that you'd call it with 4 in your case,
// as it's inclusive of minCount.
// Note this assumes C# 8 and its lovely switch expression support.
// It could be written with if/else etc of course.
public static bool HasAtMinElements<T>(this IEnumerable<T> source, int minCount) =>
    source switch
    {
        null => throw new ArgumentNullException(nameof(source)),
        ICollection<TSource> coll => coll.Count >= minCount,
        ICollection coll => coll.Count >= minCount,
        _ => source.Skip(minCount - 1).Any();
    }

That's annoying though :( Note that it doesn't optimize IIListProvider<T> like the real Count() method does, either - because that's internal.

Upvotes: 8

Nurhak Kaya
Nurhak Kaya

Reputation: 1781

Enumerable.Count Method is the Microsoft's recommended way to return the number of elements in a sequence, which is what you are already doing and it is the best option as far as I see.

Upvotes: -2

Related Questions