Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Efficient Linq Enumerable's 'Count() == 1' test

Tags:

c#

linq

Similar to this question but rephrased for Linq:

You can use Enumerable<T>.Any() to test if the enumerable contains data. But what's the efficient way to test if the enumerable contains a single value (i.e. Enumerable<T>.Count() == 1) or greater than a single value (i.e. Enumerable<T>.Count() > 1) without using an expensive count operation?

like image 500
E.Beach Avatar asked May 19 '11 13:05

E.Beach


People also ask

Which is faster any or count C#?

Any() is ALWAYS faster than . Count() > 0 ).

Is any faster than count?

Across the array sizes the Any is roughly 1/3 faster than using Count .

How do you count in Linq?

In LINQ, you can count the total number of elements present in the given sequence by using the Count Method. This method returns the total number of elements present in the given sequence.

What is Linq enumerable?

Filters a sequence of values based on a predicate. Filters a sequence of values based on a predicate. Each element's index is used in the logic of the predicate function.


6 Answers

int constrainedCount = yourSequence.Take(2).Count();

// if constrainedCount == 0 then the sequence is empty
// if constrainedCount == 1 then the sequence contains a single element
// if constrainedCount == 2 then the sequence has more than one element
like image 54
LukeH Avatar answered Sep 29 '22 00:09

LukeH


One way is to write a new extension method

public static bool IsSingle<T>(this IEnumerable<T> enumerable) {
  using (var enumerator = enumerable.GetEnumerator()) {
    if (!enumerator.MoveNext()) {
      return false;
    }
    return !enumerator.MoveNext();
  }
}
like image 25
JaredPar Avatar answered Sep 29 '22 01:09

JaredPar


This code take's LukeH's excellent answer and wraps it up as an IEnumerable extension so that your code can deal in terms of None, One and Many rather than 0, 1 and 2.

public enum Multiplicity
{
    None,
    One,
    Many,
}

In a static class, e.g. EnumerableExtensions:

public static Multiplicity Multiplicity<TElement>(this IEnumerable<TElement> @this)
{
    switch (@this.Take(2).Count())
    {
        case 0: return General.Multiplicity.None;
        case 1: return General.Multiplicity.One;
        case 2: return General.Multiplicity.Many;
        default: throw new Exception("WTF‽");
    }
}
like image 44
Paul Ruane Avatar answered Sep 29 '22 01:09

Paul Ruane


Another way:

bool containsMoreThanOneElement = yourSequence.Skip(1).Any();

Or for exactly 1 element:

bool containsOneElement = yourSequence.Any() && !yourSequence.Skip(1).Any();
like image 42
CodeNaked Avatar answered Sep 29 '22 02:09

CodeNaked


Efficient Count() == n test:

public static bool CountIsEqualTo<T>(this IEnumerable<T> enumerable, int c) 
{
    using (var enumerator = enumerable.GetEnumerator()) 
    {
        for(var i = 0; i < c ; i++)
            if (!enumerator.MoveNext()) 
                return false;

        return !enumerator.MoveNext();
    }
}
like image 42
3dGrabber Avatar answered Sep 29 '22 01:09

3dGrabber


With linq to objects, SingleOrDefault throws if there is more than one element, so you're probably best off if you roll your own.

EDIT: Now I've seen LukeH's answer, and I have to say I prefer it. Wish I'd thought of it myself!

like image 27
phoog Avatar answered Sep 29 '22 01:09

phoog