Efficient way to check if IEnumerable contains exactly one element

Viewed 56

I have an IEnumerable sequence that is lazy loaded from a Stream. It's possible that the steam might be very large (think GBs).

I need to know if the sequence contains exactly one element. Checking if .Count() == 1 is not efficient because it would enumerate the entire list by reading the complete stream. Using .Any is not useful because I need to know if it contains exactly one element, not that it contains any elements.

Possible solution

Would .Take(2).ToList() and then do a count be the most efficient way to check if a sequence contains exactly one element?

2 Answers

Since you asked for "efficient", something like this will avoid some of the allocation overhead of LINQ

int HasOne<T>(this IEnumerable<T> collection)
{
    // avoid allocating an enumerator if possible.
    if (collection.TryGetNonEnumeratedCount(out int actualCount))
    {
        return actualCount == 1;
    }

    // avoid allocating the LINQ IEnumerables for Take().
    using IEnumerator<T> e = collection.GetEnumerator();
    return e.MoveNext() && !e.MoveNext();
}

You can Take at most 2 items and then call Count():

bool exactlyOne = source.Take(2).Count() == 1;

in the worst case we'll read just first two items.

Related