Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 644
Luke101 Avatar asked Mar 28 '16 00:03

Luke101


3 Answers

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.

like image 78
Ian Mercer Avatar answered Nov 11 '22 21:11

Ian Mercer


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;
}
like image 36
Corey Avatar answered Nov 11 '22 22:11

Corey


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.

like image 27
Steve Harris Avatar answered Nov 11 '22 22:11

Steve Harris