Is there a LINQ extension or (a reasonable / effective set of LINQ attachments) that determine if a collection has at least x elements?

I have code that should know that a collection should not be empty or contain only one element.

In general, I want a form extension:

bool collectionHasAtLeast2Items = collection.AtLeast(2);

I can easily write an extension, listing by collection and increasing the indexer until I click on the requested size or exit the elements, but is there something already in the LINQ structure that will do this? My thoughts (in the order that came to me):

bool collectionHasAtLeast2Items = collection.Take(2).Count() == 2; or

bool collectionHasAtLeast2Items = collection.Take(2).ToList().Count == 2;

This would seem to work, although the behavior of taking more elements than the collection contains is not defined (in the documentation) by the Enumerable.Take Method , however, it seems to do what you would expect.

This is not the most efficient solution, listing once to take the elements and then listing them again to count them, which is optional, or listing once to pick the elements, and then creating a list to get the count property, which is n ' t enumerator-y since I really don't want a list.

This is not very good, because I always have to make two statements, first taking β€œx” and then checking that I really got β€œx”, and this depends on undocumented behavior.

Or maybe I could use:

bool collectionHasAtLeast2Items = collection.ElementAtOrDefault(2) != null;

However, this is not semantically understandable. Maybe it's best to wrap this with a method name, which means what I want. I guess it will be effective, I did not think about the code.

Some other thoughts use Last() , but I clearly don't want to list the entire collection.

Or maybe Skip(2).Any() , again semantically quite obvious, but better than ElementAtOrDefault(2) != null , although I think they give the same result?

Any thoughts?

+8
performance c # enumeration linq
source share
3 answers
 public static bool AtLeast<T>(this IEnumerable<T> source, int count) { // Optimization for ICollection<T> var genericCollection = source as ICollection<T>; if (genericCollection != null) return genericCollection.Count >= count; // Optimization for ICollection var collection = source as ICollection; if (collection != null) return collection.Count >= count; // General case using (var en = source.GetEnumerator()) { int n = 0; while (n < count && en.MoveNext()) n++; return n == count; } } 
+4
source share

Can you use Count() >= 2 if you are doing an ICollection sequence?


Behind the Enumerable.Count() scene, the verification of the extension method performs a sequence under the ICollection loop. If this is true, the Count property is returned, so the target performance should be O (1).

So ((IEnumerable<T>)((ICollection)sequence)).Count() >= x should also have O (1).

+4
source share

You can use Count , but if performance is a problem, you'll be better off with Take .

 bool atLeastX = collection.Take(x).Count() == x; 

Since Take (I believe) uses deferred execution, it will only go through the collection once.

Abatishchev noted that Count is O (1) with ICollection , so you can do something like this and get the best of both worlds.

 IEnumerable<int> col; // set col int x; // set x bool atLeastX; if (col is ICollection<int>) { atLeastX = col.Count() >= x; } else { atLeastX = col.Take(x).Count() == x; } 

You can also use Skip/Any , in fact, I'm sure it will be even faster than Take/Count .

+3
source share

All Articles