Luke101
Luke101

Reputation: 65248

Efficient way to determine collection has at least 2 items

I am aware that Linq provides capability to determine if a collection has any items. Such as

var anyCategories= categories.Any();

This is very efficient because if it finds at least one item then the iteration stops. Now what if I want to know if a collection has at least 2 items. Here is the code i have currently:

var atLeastTwoCategories= categories.Count() > 1;

This one will go through the whole collection then if the count is bigger than one. I think this is very inefficient. Does Linq or .NET provide a better way to do this?

Upvotes: 12

Views: 1821

Answers (3)

Corey
Corey

Reputation: 16564

To implement an AtLeast(n) operation that returns true if the collection contains n or more items you need to iterate through the collection n - 1 times then check to see if there are any more items remaining. Or to put it in code:

public static bool AtLeast<T>(this IEnumerable<T> collection, int n)
{
    if (n < 1)
        return true; // or exception, you choose
    if (n == 1)
        return collection.Any();
    return collection.Skip(n - 1).Any();
}

This will not require a full iteration of the collection so should be reasonably efficient.

You can try to improve on the efficiency by adding specific versions for Array<T>, List<T> and any other types that you can think of a better way. For instance:

public static bool AtLeast<T>(this Array<T> array, int n)
{
    return array.Length >= n;
}

Upvotes: 7

Ian Mercer
Ian Mercer

Reputation: 39277

Simplest approach is:

var atLeastTwoCategories= categories.Skip(1).Any();

And I'm assuming that by 'collection' you actually mean any IEnumerable supported by LINQ including, say, a SQL data source. For List and Array .NET may optimize Count down to an O(1) operation anyway so it makes no difference there. See https://stackoverflow.com/a/981283/224370 but for 'collections' coming from a database or where it's costly to iterate over the elements, this approach is faster.

Upvotes: 20

Steve Harris
Steve Harris

Reputation: 5109

Don't use the method Count(), use the property Count! (remove the brackets)

This should just return the length of the array without attempting any filtering logic.

Upvotes: 3

Related Questions