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?
Any() is ALWAYS faster than . Count() > 0 ).
Across the array sizes the Any is roughly 1/3 faster than using Count .
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.
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.
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
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();
}
}
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‽");
}
}
Another way:
bool containsMoreThanOneElement = yourSequence.Skip(1).Any();
Or for exactly 1 element:
bool containsOneElement = yourSequence.Any() && !yourSequence.Skip(1).Any();
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();
}
}
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!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With