Counting elements meeting a predicate in an enumerable without iterating the entire sequence

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;







up vote
18
down vote

favorite
1












I was reading this question, and the answer that mentioned streams, and a thought had occurred to me.



In many cases (at least in my usage) I want to determine if a sequence (or IEnumerable) has at least a certain number of elements, or has no more than a certain number, etc, that all match a predicate.



As it stands now, we have the IEnumerable<T>.Count(Func<T, bool>) method, but it will enumerate the entire IEnumerable<T> before returning. In some cases, we know we only care if there are certain numbers of values. (Such as exactly 8.)



As a result, I've built out a set of new extension methods to IEnumerable<T>, that add some functionality for counting only as needed. That is, if we care that we only have at least n, we can now deal with that in particular.



public static class IEnumerableTCountExtensions

public static bool CountAtLeast<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

var count = 0;
foreach (T item in items)

if (predicate(item))

count++;
if (count == required) break;


return count == required;

public static bool CountAbove<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

var count = 0;
foreach (T item in items)

if (predicate(item))

count++;
if (count > required) break;


return count > required;

public static bool CountEqual<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

var count = 0;
foreach (T item in items)

if (predicate(item))

count++;
if (count > required) return false;


return count == required;

public static bool CountNotEqual<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

var count = 0;
foreach (T item in items)

if (predicate(item))

count++;
if (count > required) return true;


return count != required;

public static bool CountBelow<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

var count = 0;
foreach (T item in items)

if (predicate(item))

count++;
if (count >= required) return false;


return count < required;

public static bool CountNoMoreThan<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

var count = 0;
foreach (T item in items)

if (predicate(item))

count++;
if (count == required) return false;


return count <= required;




There are 6 functions: one for each of the following:




  • >=: CountAtLeast;


  • >: CountAbove;


  • ==: CountEqual;


  • !=: CountNotEqual;


  • <: CountBelow;


  • <=: CountNoMoreThan;

Each of them short-circuits as reasonable, to allow us to only enumerate what we have to. The short-circuit path is taken in the case that it's acceptable.



A quick set of tests, with a pass/fail for each, is:



var things = new 1, 2, 3, 4, 5 .AsEnumerable().Select(x => Console.WriteLine(x); return x; );
Console.WriteLine("T? " + things.CountAtLeast(x => x <= 5, 2));
Console.WriteLine("F? " + things.CountAtLeast(x => x <= 5, 6));
Console.WriteLine("T? " + things.CountAbove(x => x <= 5, 2));
Console.WriteLine("F? " + things.CountAbove(x => x <= 5, 5));
Console.WriteLine("F? " + things.CountEqual(x => x <= 5, 2));
Console.WriteLine("T? " + things.CountEqual(x => x <= 5, 5));
Console.WriteLine("F? " + things.CountEqual(x => x <= 5, 6));
Console.WriteLine("T? " + things.CountNotEqual(x => x <= 5, 2));
Console.WriteLine("F? " + things.CountNotEqual(x => x <= 5, 5));
Console.WriteLine("T? " + things.CountNotEqual(x => x <= 5, 6));
Console.WriteLine("T? " + things.CountBelow(x => x <= 5, 6));
Console.WriteLine("F? " + things.CountBelow(x => x <= 5, 2));
Console.WriteLine("T? " + things.CountNoMoreThan(x => x <= 5, 6));
Console.WriteLine("F? " + things.CountNoMoreThan(x => x <= 5, 2));


The Console.WriteLine(x); is included to demonstrate that each item is only being iterated as maximally necessary, and can be removed for easier visual.







share|improve this question

























    up vote
    18
    down vote

    favorite
    1












    I was reading this question, and the answer that mentioned streams, and a thought had occurred to me.



    In many cases (at least in my usage) I want to determine if a sequence (or IEnumerable) has at least a certain number of elements, or has no more than a certain number, etc, that all match a predicate.



    As it stands now, we have the IEnumerable<T>.Count(Func<T, bool>) method, but it will enumerate the entire IEnumerable<T> before returning. In some cases, we know we only care if there are certain numbers of values. (Such as exactly 8.)



    As a result, I've built out a set of new extension methods to IEnumerable<T>, that add some functionality for counting only as needed. That is, if we care that we only have at least n, we can now deal with that in particular.



    public static class IEnumerableTCountExtensions

    public static bool CountAtLeast<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

    var count = 0;
    foreach (T item in items)

    if (predicate(item))

    count++;
    if (count == required) break;


    return count == required;

    public static bool CountAbove<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

    var count = 0;
    foreach (T item in items)

    if (predicate(item))

    count++;
    if (count > required) break;


    return count > required;

    public static bool CountEqual<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

    var count = 0;
    foreach (T item in items)

    if (predicate(item))

    count++;
    if (count > required) return false;


    return count == required;

    public static bool CountNotEqual<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

    var count = 0;
    foreach (T item in items)

    if (predicate(item))

    count++;
    if (count > required) return true;


    return count != required;

    public static bool CountBelow<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

    var count = 0;
    foreach (T item in items)

    if (predicate(item))

    count++;
    if (count >= required) return false;


    return count < required;

    public static bool CountNoMoreThan<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

    var count = 0;
    foreach (T item in items)

    if (predicate(item))

    count++;
    if (count == required) return false;


    return count <= required;




    There are 6 functions: one for each of the following:




    • >=: CountAtLeast;


    • >: CountAbove;


    • ==: CountEqual;


    • !=: CountNotEqual;


    • <: CountBelow;


    • <=: CountNoMoreThan;

    Each of them short-circuits as reasonable, to allow us to only enumerate what we have to. The short-circuit path is taken in the case that it's acceptable.



    A quick set of tests, with a pass/fail for each, is:



    var things = new 1, 2, 3, 4, 5 .AsEnumerable().Select(x => Console.WriteLine(x); return x; );
    Console.WriteLine("T? " + things.CountAtLeast(x => x <= 5, 2));
    Console.WriteLine("F? " + things.CountAtLeast(x => x <= 5, 6));
    Console.WriteLine("T? " + things.CountAbove(x => x <= 5, 2));
    Console.WriteLine("F? " + things.CountAbove(x => x <= 5, 5));
    Console.WriteLine("F? " + things.CountEqual(x => x <= 5, 2));
    Console.WriteLine("T? " + things.CountEqual(x => x <= 5, 5));
    Console.WriteLine("F? " + things.CountEqual(x => x <= 5, 6));
    Console.WriteLine("T? " + things.CountNotEqual(x => x <= 5, 2));
    Console.WriteLine("F? " + things.CountNotEqual(x => x <= 5, 5));
    Console.WriteLine("T? " + things.CountNotEqual(x => x <= 5, 6));
    Console.WriteLine("T? " + things.CountBelow(x => x <= 5, 6));
    Console.WriteLine("F? " + things.CountBelow(x => x <= 5, 2));
    Console.WriteLine("T? " + things.CountNoMoreThan(x => x <= 5, 6));
    Console.WriteLine("F? " + things.CountNoMoreThan(x => x <= 5, 2));


    The Console.WriteLine(x); is included to demonstrate that each item is only being iterated as maximally necessary, and can be removed for easier visual.







    share|improve this question





















      up vote
      18
      down vote

      favorite
      1









      up vote
      18
      down vote

      favorite
      1






      1





      I was reading this question, and the answer that mentioned streams, and a thought had occurred to me.



      In many cases (at least in my usage) I want to determine if a sequence (or IEnumerable) has at least a certain number of elements, or has no more than a certain number, etc, that all match a predicate.



      As it stands now, we have the IEnumerable<T>.Count(Func<T, bool>) method, but it will enumerate the entire IEnumerable<T> before returning. In some cases, we know we only care if there are certain numbers of values. (Such as exactly 8.)



      As a result, I've built out a set of new extension methods to IEnumerable<T>, that add some functionality for counting only as needed. That is, if we care that we only have at least n, we can now deal with that in particular.



      public static class IEnumerableTCountExtensions

      public static bool CountAtLeast<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

      var count = 0;
      foreach (T item in items)

      if (predicate(item))

      count++;
      if (count == required) break;


      return count == required;

      public static bool CountAbove<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

      var count = 0;
      foreach (T item in items)

      if (predicate(item))

      count++;
      if (count > required) break;


      return count > required;

      public static bool CountEqual<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

      var count = 0;
      foreach (T item in items)

      if (predicate(item))

      count++;
      if (count > required) return false;


      return count == required;

      public static bool CountNotEqual<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

      var count = 0;
      foreach (T item in items)

      if (predicate(item))

      count++;
      if (count > required) return true;


      return count != required;

      public static bool CountBelow<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

      var count = 0;
      foreach (T item in items)

      if (predicate(item))

      count++;
      if (count >= required) return false;


      return count < required;

      public static bool CountNoMoreThan<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

      var count = 0;
      foreach (T item in items)

      if (predicate(item))

      count++;
      if (count == required) return false;


      return count <= required;




      There are 6 functions: one for each of the following:




      • >=: CountAtLeast;


      • >: CountAbove;


      • ==: CountEqual;


      • !=: CountNotEqual;


      • <: CountBelow;


      • <=: CountNoMoreThan;

      Each of them short-circuits as reasonable, to allow us to only enumerate what we have to. The short-circuit path is taken in the case that it's acceptable.



      A quick set of tests, with a pass/fail for each, is:



      var things = new 1, 2, 3, 4, 5 .AsEnumerable().Select(x => Console.WriteLine(x); return x; );
      Console.WriteLine("T? " + things.CountAtLeast(x => x <= 5, 2));
      Console.WriteLine("F? " + things.CountAtLeast(x => x <= 5, 6));
      Console.WriteLine("T? " + things.CountAbove(x => x <= 5, 2));
      Console.WriteLine("F? " + things.CountAbove(x => x <= 5, 5));
      Console.WriteLine("F? " + things.CountEqual(x => x <= 5, 2));
      Console.WriteLine("T? " + things.CountEqual(x => x <= 5, 5));
      Console.WriteLine("F? " + things.CountEqual(x => x <= 5, 6));
      Console.WriteLine("T? " + things.CountNotEqual(x => x <= 5, 2));
      Console.WriteLine("F? " + things.CountNotEqual(x => x <= 5, 5));
      Console.WriteLine("T? " + things.CountNotEqual(x => x <= 5, 6));
      Console.WriteLine("T? " + things.CountBelow(x => x <= 5, 6));
      Console.WriteLine("F? " + things.CountBelow(x => x <= 5, 2));
      Console.WriteLine("T? " + things.CountNoMoreThan(x => x <= 5, 6));
      Console.WriteLine("F? " + things.CountNoMoreThan(x => x <= 5, 2));


      The Console.WriteLine(x); is included to demonstrate that each item is only being iterated as maximally necessary, and can be removed for easier visual.







      share|improve this question











      I was reading this question, and the answer that mentioned streams, and a thought had occurred to me.



      In many cases (at least in my usage) I want to determine if a sequence (or IEnumerable) has at least a certain number of elements, or has no more than a certain number, etc, that all match a predicate.



      As it stands now, we have the IEnumerable<T>.Count(Func<T, bool>) method, but it will enumerate the entire IEnumerable<T> before returning. In some cases, we know we only care if there are certain numbers of values. (Such as exactly 8.)



      As a result, I've built out a set of new extension methods to IEnumerable<T>, that add some functionality for counting only as needed. That is, if we care that we only have at least n, we can now deal with that in particular.



      public static class IEnumerableTCountExtensions

      public static bool CountAtLeast<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

      var count = 0;
      foreach (T item in items)

      if (predicate(item))

      count++;
      if (count == required) break;


      return count == required;

      public static bool CountAbove<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

      var count = 0;
      foreach (T item in items)

      if (predicate(item))

      count++;
      if (count > required) break;


      return count > required;

      public static bool CountEqual<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

      var count = 0;
      foreach (T item in items)

      if (predicate(item))

      count++;
      if (count > required) return false;


      return count == required;

      public static bool CountNotEqual<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

      var count = 0;
      foreach (T item in items)

      if (predicate(item))

      count++;
      if (count > required) return true;


      return count != required;

      public static bool CountBelow<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

      var count = 0;
      foreach (T item in items)

      if (predicate(item))

      count++;
      if (count >= required) return false;


      return count < required;

      public static bool CountNoMoreThan<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

      var count = 0;
      foreach (T item in items)

      if (predicate(item))

      count++;
      if (count == required) return false;


      return count <= required;




      There are 6 functions: one for each of the following:




      • >=: CountAtLeast;


      • >: CountAbove;


      • ==: CountEqual;


      • !=: CountNotEqual;


      • <: CountBelow;


      • <=: CountNoMoreThan;

      Each of them short-circuits as reasonable, to allow us to only enumerate what we have to. The short-circuit path is taken in the case that it's acceptable.



      A quick set of tests, with a pass/fail for each, is:



      var things = new 1, 2, 3, 4, 5 .AsEnumerable().Select(x => Console.WriteLine(x); return x; );
      Console.WriteLine("T? " + things.CountAtLeast(x => x <= 5, 2));
      Console.WriteLine("F? " + things.CountAtLeast(x => x <= 5, 6));
      Console.WriteLine("T? " + things.CountAbove(x => x <= 5, 2));
      Console.WriteLine("F? " + things.CountAbove(x => x <= 5, 5));
      Console.WriteLine("F? " + things.CountEqual(x => x <= 5, 2));
      Console.WriteLine("T? " + things.CountEqual(x => x <= 5, 5));
      Console.WriteLine("F? " + things.CountEqual(x => x <= 5, 6));
      Console.WriteLine("T? " + things.CountNotEqual(x => x <= 5, 2));
      Console.WriteLine("F? " + things.CountNotEqual(x => x <= 5, 5));
      Console.WriteLine("T? " + things.CountNotEqual(x => x <= 5, 6));
      Console.WriteLine("T? " + things.CountBelow(x => x <= 5, 6));
      Console.WriteLine("F? " + things.CountBelow(x => x <= 5, 2));
      Console.WriteLine("T? " + things.CountNoMoreThan(x => x <= 5, 6));
      Console.WriteLine("F? " + things.CountNoMoreThan(x => x <= 5, 2));


      The Console.WriteLine(x); is included to demonstrate that each item is only being iterated as maximally necessary, and can be removed for easier visual.









      share|improve this question










      share|improve this question




      share|improve this question









      asked May 2 at 21:02









      202_accepted

      14.8k247126




      14.8k247126




















          8 Answers
          8






          active

          oldest

          votes

















          up vote
          13
          down vote



          accepted










          There are so many different solutions already that I won't post another. But there is something else that bothers me, the names of the extensions. I find they are too confusing. Expecially Above and Below. They are not very technical (at leat in this context).



          I think they should be called the same way we call the conditions they are based on and that are (or should be) familiar to all developers. This means:



          Two of them already folow that pattern:



          CountEqual
          CountNotEqual


          The rest should be:



          CountLessThan
          CountLessThanOrEqual
          CountGreaterThan
          CountGreaterThanOrEqual





          share|improve this answer





















          • Totally agree, I screwed the pooch on that one. :)
            – 202_accepted
            May 3 at 11:40

















          up vote
          16
          down vote













          You can use the Linq Take to accomplish the same thing



          public static class IEnumerableTCountExtensions

          public static bool CountAtLeast<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

          var count = items.Where(predicate).Take(required).Count();
          return count == required;

          public static bool CountAbove<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

          var count = items.Where(predicate).Take(required + 1).Count();
          return count > required;

          public static bool CountEqual<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

          var count = items.Where(predicate).Take(required + 1).Count();
          return count == required;

          public static bool CountNotEqual<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

          var count = items.Where(predicate).Take(required + 1).Count();
          return count != required;

          public static bool CountBelow<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

          var count = items.Where(predicate).Take(required).Count();
          return count < required;

          public static bool CountNoMoreThan<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

          var count = items.Where(predicate).Take(required + 1).Count();
          return count <= required;




          The only different in enumeration is the CountNoMoreThan as the original code has a short circuit on if (count == required) return false; which wouldn't know if there are more just that we hit the target and return false so it would seem a less than clause and not a less than or equal to. I'm thinking this might be a bug in the original code since the return statement is doing a less than or equals.



          Also should add the guard clauses like Jesse C. Slicer suggested.






          share|improve this answer

















          • 1




            MoreLinq is also available. It contains AssertCount, AtLeast and AtMost.
            – Dan Friedman
            May 3 at 2:52










          • Doesn't an in-memory IEnumerable (i.e. not an IQueryable) iterate over the entire array directly when calling Where()? If so, that would defeat OP's purpose. Or does it still do the "IQueryable approach" (deferred execution) even if the collection is in-memory?
            – Flater
            May 3 at 7:53






          • 5




            @Flater yes, execution is deferred.
            – Adriano Repetti
            May 3 at 7:58










          • Aye, this is how I would do it in F#, so it makes sense to do the same here. :)
            – 202_accepted
            May 3 at 11:44

















          up vote
          8
          down vote













          With the help of LINQ and some helper methods, you can achieve the same with a lot less repetitive code.



          How do we do it? Well we extract the foreach loop into an iterator which will return the current count of predicate matches:



          private static IEnumerable<int> GetMatchingValues<T>(IEnumerable<T> items, Predicate<T> predicate)

          int count = 0;
          foreach (var item in items)

          if (predicate.Invoke(item))

          yield return ++count;





          Once you have that it's a lot easier to see the pattern, most of those functions are either .Any or .All invocations, except for 1 odd case which really annoys me, perhaps someone smarter can figure it out:



          public static bool CountAtLeast<T>(this IEnumerable<T> items, Predicate<T> predicate, int required)

          return GetMatchingValues(items, predicate).Any(count => count == required);


          public static bool CountAbove<T>(this IEnumerable<T> items, Predicate<T> predicate, int required)

          return GetMatchingValues(items, predicate).Any(count => count > required);


          public static bool CountEqual<T>(this IEnumerable<T> items, Predicate<T> predicate, int required)

          int finalCount = 0;
          foreach (int count in GetMatchingValues(items, predicate))

          finalCount = count;
          if (finalCount > required) break;

          return finalCount == required;


          public static bool CountNotEqual<T>(this IEnumerable<T> items, Predicate<T> predicate, int required)

          return !CountEqual(items, predicate, required);


          public static bool CountBelow<T>(this IEnumerable<T> items, Predicate<T> predicate, int required)

          return !GetMatchingValues(items, predicate).Any(count => count >= required);


          public static bool CountNoMoreThan<T>(this IEnumerable<T> items, Predicate<T> predicate, int required)

          return GetMatchingValues(items, predicate).All(count => count != required);






          share|improve this answer



















          • 2




            @Flater the iterator does not know when the end is. That's why it returns all the values. If you believe there is a cleaner approach please post an answer or add a short snippet in Fiddle and drop it here. I will be very interested in it.
            – Denis
            May 3 at 7:32






          • 1




            @Flater It is effectively omitting the local variable declaration and it allows us to operate on the predicate matches as a sequence of elements instead of separate integers. It's true that only the last is important but I don't see a way of doing it otherwise, that's why I asked you to add a snippet if you know a better way of doing it.
            – Denis
            May 3 at 7:41






          • 1




            @Flater The iterator is not aware of the magic number. It needs to return 1,2,3,4,5 because the iterator does not know the magic number is 5. The magic number may have been 3.
            – paparazzo
            May 3 at 9:36






          • 1




            @Flater The benefit is less repeated code compared to the OP.
            – paparazzo
            May 3 at 10:16






          • 1




            @Flater would you like to continue the discussion in a chat room? I feel there is some misunderstanding here.
            – Denis
            May 3 at 10:54

















          up vote
          7
          down vote













          Two minor recommendations:



          1. Rename items to source to be in-line with how LINQ does it.


          2. Add parameter checking to the beginning of the methods as LINQ does:



             if (source == null)

            throw new ArgumentNullException(nameof(source));


            if (predicate == null)

            throw new ArgumentNullException(nameof(predicate));



          And it looks solid!



          ETA: Given the other super-cool answers, adding in the magic of C#7, I've refactored a little bit:



          public static class IEnumerableTCountExtensions

          public static bool CountGreaterThanOrEqual<T>(this IEnumerable<T> source, Func<T, bool> predicate, int required) => source == null
          ? throw new ArgumentNullException(nameof(source))
          : (predicate == null
          ? throw new ArgumentNullException(nameof(predicate))
          : source.Where(predicate).Take(required).Count() == required);

          public static bool CountGreaterThan<T>(this IEnumerable<T> source, Func<T, bool> predicate, int required) => source == null
          ? throw new ArgumentNullException(nameof(source))
          : (predicate == null
          ? throw new ArgumentNullException(nameof(predicate))
          : source.Where(predicate).Take(required + 1).Count() > required);

          public static bool CountEqual<T>(this IEnumerable<T> source, Func<T, bool> predicate, int required) => source == null
          ? throw new ArgumentNullException(nameof(source))
          : (predicate == null
          ? throw new ArgumentNullException(nameof(predicate))
          : source.Where(predicate).Take(required + 1).Count() == required);

          public static bool CountNotEqual<T>(this IEnumerable<T> source, Func<T, bool> predicate, int required) => source == null
          ? throw new ArgumentNullException(nameof(source))
          : (predicate == null
          ? throw new ArgumentNullException(nameof(predicate))
          : source.Where(predicate).Take(required + 1).Count() != required);

          public static bool CountLessThan<T>(this IEnumerable<T> source, Func<T, bool> predicate, int required) => source == null
          ? throw new ArgumentNullException(nameof(source))
          : (predicate == null
          ? throw new ArgumentNullException(nameof(predicate))
          : source.Where(predicate).Take(required).Count() < required);

          public static bool CountLessThanOrEqual<T>(this IEnumerable<T> source, Func<T, bool> predicate, int required) => source == null
          ? throw new ArgumentNullException(nameof(source))
          : (predicate == null
          ? throw new ArgumentNullException(nameof(predicate))
          : source.Where(predicate).Take(required + 1).Count() <= required);






          share|improve this answer



















          • 1




            I know this is just a style preference but I never like using ternary conditional operator for throwing. I prefer to either have the guard clause or have a static guard class that does the checking. Or even better to use code contracts.
            – CharlesNRice
            May 3 at 13:32

















          up vote
          5
          down vote













          The action which is taken if the if condition is true isn't consitent. Sometimes you return out of the if and sometimes you break out of the loop althougth you could do it the same way.



          E.g



          In CountAbove you break if count > required to return count > required but in CountEqual you return false if count > required and if that if condition is never evaluated to true you return count == required.




          You could use some pre-check to make sure you won't need to iterate at all by soft-casting the IEnumerable<T> items to an ICollection<T>/ICollection and if the soft-cast succeed you can check the Count property.



          You may say but what about the predicate? Well e.g. for CountAbove the Count property of the ICollection<T>/ICollection needs to be at least greater than required like so



          public static bool CountAbove<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

          ICollection<T> collectionOfT = items as ICollection<T>;
          if (collectionOfT != null && collectionOfT.Count <= required) return false;
          ICollection collection = items as ICollection;
          if (collection != null && collection.Count <= required) return false;

          var count = 0;
          foreach (T item in items)

          if (predicate(item))

          count++;
          if (count > required) break;


          return count > required;






          share|improve this answer




























            up vote
            5
            down vote













            This is a variation on Denis' answer. While his answer works, it is returning a progressive count (1,2,3,4,5) for no good reason. In the end, you're only interested in the last number (5) that is returned, so there is no point to wrapping the count in an IEnumerable.



            Furthermore, because of the combined use of logical inversions, Any and All, Denis' code (while it does work) becomes quite hard to quickly read through. There is a difference between e.g. !myList.All(x => x == myValue) and myList.All(x => x != myValue), but the distinction is hard to miss here.



            Comparatively, the distinction between myCount == myValue and myCount != myValue is much easier to parse at a glance, which is why I think my answer is better from a readability standpoint (even though it is functionally equivalent, which I do concede).




            The counting algorithm



            private static int CountMatchesUpTo<T>(IEnumerable<T> items, Predicate<T> predicate, int boundary)

            int count = 0;
            foreach (var item in items)

            if (predicate.Invoke(item))

            count++;


            if(count == boundary)

            break;



            return count;



            There are two possible ways that the return statement can be reached:



            • Because the foreach completed. This happens if you have less than boundary matches in your list, since you keep looking for matches up to the boundary.

            • Because the boundary was reached. At this point, the foreach is forcefully broken out of, and the count (equal to boundary) is returned. The remaining items of the list were never iterated over.


            The wrapper methods



            The implementation of most of the other methods is relatively easy to do.



            Notice that in some cases, I use required + 1 as the upper bound. This is relevant in cases where you want to distinguish between a match count that is either equal to or greater than the boundary.



            Assuming you're using a boundary of 5, you then instruct the counting method to look for 6 items.



            • If it returns 6, then you know that there are more than 5 matches.

            • If it returns 5, then you know that there are exactly 5 matches (the same applies for a smaller return value).

            This takes care of the "upper" short circuit. The "lower" short circuit is already taken care of as you will receive a lower number if not enough matches were found.



            public static bool CountEqual<T>(this IEnumerable<T> items, Predicate<T> predicate, int required)

            return CountMatchesUpTo(items, predicate, required + 1) == required;


            public static bool CountNotEqual<T>(this IEnumerable<T> items, Predicate<T> predicate, int required)

            return CountMatchesUpTo(items, predicate, required + 1) != required;


            public static bool CountAbove<T>(this IEnumerable<T> items, Predicate<T> predicate, int required)

            return CountMatchesUpTo(items, predicate, required + 1) > required;


            public static bool CountAtLeast<T>(this IEnumerable<T> items, Predicate<T> predicate, int required)

            return CountMatchesUpTo(items, predicate, required) == required;




            public static bool CountBelow<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

            var count = 0;
            foreach (T item in items)

            if (predicate(item))

            count++;
            if (count >= required) return false;


            return count < required;


            public static bool CountNoMoreThan<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

            var count = 0;
            foreach (T item in items)

            if (predicate(item))

            count++;
            if (count == required) return false;


            return count <= required;



            There are two things to notice here:



            1 - In one method, you do if (count >= required) return false; , and in the other, you do if (count == required) return false; . Since count is incrementing one at a time, count >= required will evaluate to true because it count is equal to required. Count will never be greater than required since you exit the method when it already equals it.



            2 - CountNoMoreThan is also unintuitive for another reason: you do if (count == required) return false; and then return count <= required;.

            The return statement will never find a case where count equals required, since you've already explicitly returned false when you find an equality. The return statement can therefore be refactored to return count < required;.



            Combining the findings of 1 and 2, this means that CountBelow and CountNoMoreThan are currently functionally equivalent methods. There's no point to having both methods.



            From the method names, I surmise that the difference between the two is < or <=. Using my refactored approach, the difference is easy to implement:



            public static bool CountNoMoreThan<T>(this IEnumerable<T> items, Predicate<T> predicate, int required)

            return CountMatchesUpTo(items, predicate, required + 1) <= required;



            Note that we again use required+1, to allow for the count method to tell us if there are more matches than the boundary.



            public static bool CountBelow<T>(this IEnumerable<T> items, Predicate<T> predicate, int required)

            return CountMatchesUpTo(items, predicate, required) < required;




            Footnote



            As it stands, all the listed methods are merely an enumeration of int comparisons: ==, !=, >, >=, <, <=.



            There is little point to doing this. You can simply make CountMatchesUpTo a publically accessible method, and rely on your caller to do their own evaluation.



            If you're already expecting your caller to know which method to use, that means that they know which evaluation they want to take place. There is no added benefit from putting it in an additional method layer.



            If you're doing more cumbersome logic (e.g. checking if two datetimes overlap), that is relevant to put into a method, as it would be cumbersome to write every time. But your current evaluations are not complex enough to warrant their own method layer.



            The issue here is that your additional layer is an additional place for bugs to sneak into the code. And it already did, as I found a bug in CountNoMoreThan. If uncaught, external consumers of your methods would be hunting for bugs in their own code, unaware that your method is simply not doing what its name advertises.




            Update



            Update is not correct. See below.



            Two of your tests appear to be incorrect:



            Console.WriteLine("F? " + things.CountEqual(x => x <= 5, 2));
            Console.WriteLine("T? " + things.CountNotEqual(x => x <= 5, 2));


            Since you set the boundary at 2, the "count up to" algorithm will logically stop iterating over the collection once it reaches a count of 2.



            This means that things.CountEqual(x => x <= 5, 2) will return true, and things.CountNotEqual(x => x <= 5, 2) will return false.



            Your test seemingly expects that the counting method will still count 5 elements; which violates the algorithm (as it should stop after the defined boundary, which in this case is 2).



            It's an easy mistake to make; one that I had initially glossed over too, as I understood what you were trying to test. But the expected outcome of these two tests should be inverted; otherwise it would violate your proposed algorithm.



            Update to the update



            The requirements were clarified by OP in chat. The above code has been altered to reflect that.






            share|improve this answer



















            • 2




              As far as I like your comments (+1) I always find this argument very weak: The issue here is that your additional layer is an additional place for bugs to sneak into the code. - I treat creating convenience extensions (or any other resusable code) always a good thing because I'm a lazy engineer ;-) sure, there might be some bugs (usually at the beginning) but you know where to find them and they are easier to test and to fix and what's even more imporatnt, you're doing this only once and when you're done, you never have to implement this logic again so it's actually a good thing.
              – t3chb0t
              May 3 at 10:30











            • @t3chb0t: I'm all for convenience extensions (as I mentioned for datetime overlap). However, the current methods are wrapping the most elementary of comparison operators. There is a reasonability argument here; if the method doesn't shorten the code and choosing the correct method requires the same level of knowledge as doing the comparison yourself; there's no convenience from having the method. Comparatively, Datetime overlap comparison is a reasonable convenience, because it's cumbersome to always write the multiple comparison evaluations needed to correctly check for an overlap.
              – Flater
              May 3 at 10:36











            • For us outsiders/readers, it's always difficult to tell whether something is useful/convenient or not as we might not have the need for it yet but I guess OP might have already be using similar code multiple times so in his projects this is a convenience. Another such example could be my extensions for testing common interfaces. Not much feedback received, probalby because nobody is doing this but I'm using them in many projects; it's relative :-]
              – t3chb0t
              May 3 at 10:49











            • CountEqual and CountNotEqual don't quite work, at least the way it's posted here, you should run the tests OP has provided.
              – Denis
              May 3 at 10:51










            • @Flater those 2 tests specifically Console.WriteLine("F? " + things.CountEqual(x => x <= 5, 2));, Console.WriteLine("T? " + things.CountNotEqual(x => x <= 5, 2));.
              – Denis
              May 3 at 11:00


















            up vote
            4
            down vote













            A method that returns a count and stop at a target count can do all that logic.

            I like more mathematical names.



            public static class IEnumerableTCountExtensions

            private static int CountMatchingStopAt<T>(IEnumerable<T> items, Func<T, bool> predicate, int stopAt)

            int count = 0;
            foreach (var item in items)

            if (predicate.Invoke(item))

            count++;
            if(count == stopAt)

            break;



            return count;

            public static bool GreaterThanOrEqual<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

            return CountMatchingStopAt(items, predicate, required + 1) >= required;

            public static bool GreaterThan<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

            return CountMatchingStopAt(items, predicate, required + 1) == required + 1;

            public static bool Equal<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

            return CountMatchingStopAt(items, predicate, required + 1) == required;

            public static bool NotEqual<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

            return CountMatchingStopAt(items, predicate, required + 1) != required;

            public static bool LessThan<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

            return CountMatchingStopAt(items, predicate, required) < required;

            public static bool LessThanOrEqual<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

            return CountMatchingStopAt(items, predicate, required + 1) <= required;







            share|improve this answer






























              up vote
              3
              down vote














              Each of them short-circuits as reasonable, to allow us to only enumerate what we have to. The short-circuit path is taken in the case that it's acceptable.




              Not quite. There are some missing corner cases when required <= 0 (or required < 0 for the exact test).






              share|improve this answer





















                Your Answer




                StackExchange.ifUsing("editor", function ()
                return StackExchange.using("mathjaxEditing", function ()
                StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
                StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
                );
                );
                , "mathjax-editing");

                StackExchange.ifUsing("editor", function ()
                StackExchange.using("externalEditor", function ()
                StackExchange.using("snippets", function ()
                StackExchange.snippets.init();
                );
                );
                , "code-snippets");

                StackExchange.ready(function()
                var channelOptions =
                tags: "".split(" "),
                id: "196"
                ;
                initTagRenderer("".split(" "), "".split(" "), channelOptions);

                StackExchange.using("externalEditor", function()
                // Have to fire editor after snippets, if snippets enabled
                if (StackExchange.settings.snippets.snippetsEnabled)
                StackExchange.using("snippets", function()
                createEditor();
                );

                else
                createEditor();

                );

                function createEditor()
                StackExchange.prepareEditor(
                heartbeatType: 'answer',
                convertImagesToLinks: false,
                noModals: false,
                showLowRepImageUploadWarning: true,
                reputationToPostImages: null,
                bindNavPrevention: true,
                postfix: "",
                onDemand: true,
                discardSelector: ".discard-answer"
                ,immediatelyShowMarkdownHelp:true
                );



                );








                 

                draft saved


                draft discarded


















                StackExchange.ready(
                function ()
                StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f193499%2fcounting-elements-meeting-a-predicate-in-an-enumerable-without-iterating-the-ent%23new-answer', 'question_page');

                );

                Post as a guest






























                8 Answers
                8






                active

                oldest

                votes








                8 Answers
                8






                active

                oldest

                votes









                active

                oldest

                votes






                active

                oldest

                votes








                up vote
                13
                down vote



                accepted










                There are so many different solutions already that I won't post another. But there is something else that bothers me, the names of the extensions. I find they are too confusing. Expecially Above and Below. They are not very technical (at leat in this context).



                I think they should be called the same way we call the conditions they are based on and that are (or should be) familiar to all developers. This means:



                Two of them already folow that pattern:



                CountEqual
                CountNotEqual


                The rest should be:



                CountLessThan
                CountLessThanOrEqual
                CountGreaterThan
                CountGreaterThanOrEqual





                share|improve this answer





















                • Totally agree, I screwed the pooch on that one. :)
                  – 202_accepted
                  May 3 at 11:40














                up vote
                13
                down vote



                accepted










                There are so many different solutions already that I won't post another. But there is something else that bothers me, the names of the extensions. I find they are too confusing. Expecially Above and Below. They are not very technical (at leat in this context).



                I think they should be called the same way we call the conditions they are based on and that are (or should be) familiar to all developers. This means:



                Two of them already folow that pattern:



                CountEqual
                CountNotEqual


                The rest should be:



                CountLessThan
                CountLessThanOrEqual
                CountGreaterThan
                CountGreaterThanOrEqual





                share|improve this answer





















                • Totally agree, I screwed the pooch on that one. :)
                  – 202_accepted
                  May 3 at 11:40












                up vote
                13
                down vote



                accepted







                up vote
                13
                down vote



                accepted






                There are so many different solutions already that I won't post another. But there is something else that bothers me, the names of the extensions. I find they are too confusing. Expecially Above and Below. They are not very technical (at leat in this context).



                I think they should be called the same way we call the conditions they are based on and that are (or should be) familiar to all developers. This means:



                Two of them already folow that pattern:



                CountEqual
                CountNotEqual


                The rest should be:



                CountLessThan
                CountLessThanOrEqual
                CountGreaterThan
                CountGreaterThanOrEqual





                share|improve this answer













                There are so many different solutions already that I won't post another. But there is something else that bothers me, the names of the extensions. I find they are too confusing. Expecially Above and Below. They are not very technical (at leat in this context).



                I think they should be called the same way we call the conditions they are based on and that are (or should be) familiar to all developers. This means:



                Two of them already folow that pattern:



                CountEqual
                CountNotEqual


                The rest should be:



                CountLessThan
                CountLessThanOrEqual
                CountGreaterThan
                CountGreaterThanOrEqual






                share|improve this answer













                share|improve this answer



                share|improve this answer











                answered May 3 at 9:15









                t3chb0t

                31.9k54195




                31.9k54195











                • Totally agree, I screwed the pooch on that one. :)
                  – 202_accepted
                  May 3 at 11:40
















                • Totally agree, I screwed the pooch on that one. :)
                  – 202_accepted
                  May 3 at 11:40















                Totally agree, I screwed the pooch on that one. :)
                – 202_accepted
                May 3 at 11:40




                Totally agree, I screwed the pooch on that one. :)
                – 202_accepted
                May 3 at 11:40












                up vote
                16
                down vote













                You can use the Linq Take to accomplish the same thing



                public static class IEnumerableTCountExtensions

                public static bool CountAtLeast<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

                var count = items.Where(predicate).Take(required).Count();
                return count == required;

                public static bool CountAbove<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

                var count = items.Where(predicate).Take(required + 1).Count();
                return count > required;

                public static bool CountEqual<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

                var count = items.Where(predicate).Take(required + 1).Count();
                return count == required;

                public static bool CountNotEqual<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

                var count = items.Where(predicate).Take(required + 1).Count();
                return count != required;

                public static bool CountBelow<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

                var count = items.Where(predicate).Take(required).Count();
                return count < required;

                public static bool CountNoMoreThan<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

                var count = items.Where(predicate).Take(required + 1).Count();
                return count <= required;




                The only different in enumeration is the CountNoMoreThan as the original code has a short circuit on if (count == required) return false; which wouldn't know if there are more just that we hit the target and return false so it would seem a less than clause and not a less than or equal to. I'm thinking this might be a bug in the original code since the return statement is doing a less than or equals.



                Also should add the guard clauses like Jesse C. Slicer suggested.






                share|improve this answer

















                • 1




                  MoreLinq is also available. It contains AssertCount, AtLeast and AtMost.
                  – Dan Friedman
                  May 3 at 2:52










                • Doesn't an in-memory IEnumerable (i.e. not an IQueryable) iterate over the entire array directly when calling Where()? If so, that would defeat OP's purpose. Or does it still do the "IQueryable approach" (deferred execution) even if the collection is in-memory?
                  – Flater
                  May 3 at 7:53






                • 5




                  @Flater yes, execution is deferred.
                  – Adriano Repetti
                  May 3 at 7:58










                • Aye, this is how I would do it in F#, so it makes sense to do the same here. :)
                  – 202_accepted
                  May 3 at 11:44














                up vote
                16
                down vote













                You can use the Linq Take to accomplish the same thing



                public static class IEnumerableTCountExtensions

                public static bool CountAtLeast<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

                var count = items.Where(predicate).Take(required).Count();
                return count == required;

                public static bool CountAbove<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

                var count = items.Where(predicate).Take(required + 1).Count();
                return count > required;

                public static bool CountEqual<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

                var count = items.Where(predicate).Take(required + 1).Count();
                return count == required;

                public static bool CountNotEqual<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

                var count = items.Where(predicate).Take(required + 1).Count();
                return count != required;

                public static bool CountBelow<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

                var count = items.Where(predicate).Take(required).Count();
                return count < required;

                public static bool CountNoMoreThan<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

                var count = items.Where(predicate).Take(required + 1).Count();
                return count <= required;




                The only different in enumeration is the CountNoMoreThan as the original code has a short circuit on if (count == required) return false; which wouldn't know if there are more just that we hit the target and return false so it would seem a less than clause and not a less than or equal to. I'm thinking this might be a bug in the original code since the return statement is doing a less than or equals.



                Also should add the guard clauses like Jesse C. Slicer suggested.






                share|improve this answer

















                • 1




                  MoreLinq is also available. It contains AssertCount, AtLeast and AtMost.
                  – Dan Friedman
                  May 3 at 2:52










                • Doesn't an in-memory IEnumerable (i.e. not an IQueryable) iterate over the entire array directly when calling Where()? If so, that would defeat OP's purpose. Or does it still do the "IQueryable approach" (deferred execution) even if the collection is in-memory?
                  – Flater
                  May 3 at 7:53






                • 5




                  @Flater yes, execution is deferred.
                  – Adriano Repetti
                  May 3 at 7:58










                • Aye, this is how I would do it in F#, so it makes sense to do the same here. :)
                  – 202_accepted
                  May 3 at 11:44












                up vote
                16
                down vote










                up vote
                16
                down vote









                You can use the Linq Take to accomplish the same thing



                public static class IEnumerableTCountExtensions

                public static bool CountAtLeast<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

                var count = items.Where(predicate).Take(required).Count();
                return count == required;

                public static bool CountAbove<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

                var count = items.Where(predicate).Take(required + 1).Count();
                return count > required;

                public static bool CountEqual<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

                var count = items.Where(predicate).Take(required + 1).Count();
                return count == required;

                public static bool CountNotEqual<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

                var count = items.Where(predicate).Take(required + 1).Count();
                return count != required;

                public static bool CountBelow<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

                var count = items.Where(predicate).Take(required).Count();
                return count < required;

                public static bool CountNoMoreThan<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

                var count = items.Where(predicate).Take(required + 1).Count();
                return count <= required;




                The only different in enumeration is the CountNoMoreThan as the original code has a short circuit on if (count == required) return false; which wouldn't know if there are more just that we hit the target and return false so it would seem a less than clause and not a less than or equal to. I'm thinking this might be a bug in the original code since the return statement is doing a less than or equals.



                Also should add the guard clauses like Jesse C. Slicer suggested.






                share|improve this answer













                You can use the Linq Take to accomplish the same thing



                public static class IEnumerableTCountExtensions

                public static bool CountAtLeast<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

                var count = items.Where(predicate).Take(required).Count();
                return count == required;

                public static bool CountAbove<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

                var count = items.Where(predicate).Take(required + 1).Count();
                return count > required;

                public static bool CountEqual<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

                var count = items.Where(predicate).Take(required + 1).Count();
                return count == required;

                public static bool CountNotEqual<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

                var count = items.Where(predicate).Take(required + 1).Count();
                return count != required;

                public static bool CountBelow<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

                var count = items.Where(predicate).Take(required).Count();
                return count < required;

                public static bool CountNoMoreThan<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

                var count = items.Where(predicate).Take(required + 1).Count();
                return count <= required;




                The only different in enumeration is the CountNoMoreThan as the original code has a short circuit on if (count == required) return false; which wouldn't know if there are more just that we hit the target and return false so it would seem a less than clause and not a less than or equal to. I'm thinking this might be a bug in the original code since the return statement is doing a less than or equals.



                Also should add the guard clauses like Jesse C. Slicer suggested.







                share|improve this answer













                share|improve this answer



                share|improve this answer











                answered May 3 at 1:48









                CharlesNRice

                1,601311




                1,601311







                • 1




                  MoreLinq is also available. It contains AssertCount, AtLeast and AtMost.
                  – Dan Friedman
                  May 3 at 2:52










                • Doesn't an in-memory IEnumerable (i.e. not an IQueryable) iterate over the entire array directly when calling Where()? If so, that would defeat OP's purpose. Or does it still do the "IQueryable approach" (deferred execution) even if the collection is in-memory?
                  – Flater
                  May 3 at 7:53






                • 5




                  @Flater yes, execution is deferred.
                  – Adriano Repetti
                  May 3 at 7:58










                • Aye, this is how I would do it in F#, so it makes sense to do the same here. :)
                  – 202_accepted
                  May 3 at 11:44












                • 1




                  MoreLinq is also available. It contains AssertCount, AtLeast and AtMost.
                  – Dan Friedman
                  May 3 at 2:52










                • Doesn't an in-memory IEnumerable (i.e. not an IQueryable) iterate over the entire array directly when calling Where()? If so, that would defeat OP's purpose. Or does it still do the "IQueryable approach" (deferred execution) even if the collection is in-memory?
                  – Flater
                  May 3 at 7:53






                • 5




                  @Flater yes, execution is deferred.
                  – Adriano Repetti
                  May 3 at 7:58










                • Aye, this is how I would do it in F#, so it makes sense to do the same here. :)
                  – 202_accepted
                  May 3 at 11:44







                1




                1




                MoreLinq is also available. It contains AssertCount, AtLeast and AtMost.
                – Dan Friedman
                May 3 at 2:52




                MoreLinq is also available. It contains AssertCount, AtLeast and AtMost.
                – Dan Friedman
                May 3 at 2:52












                Doesn't an in-memory IEnumerable (i.e. not an IQueryable) iterate over the entire array directly when calling Where()? If so, that would defeat OP's purpose. Or does it still do the "IQueryable approach" (deferred execution) even if the collection is in-memory?
                – Flater
                May 3 at 7:53




                Doesn't an in-memory IEnumerable (i.e. not an IQueryable) iterate over the entire array directly when calling Where()? If so, that would defeat OP's purpose. Or does it still do the "IQueryable approach" (deferred execution) even if the collection is in-memory?
                – Flater
                May 3 at 7:53




                5




                5




                @Flater yes, execution is deferred.
                – Adriano Repetti
                May 3 at 7:58




                @Flater yes, execution is deferred.
                – Adriano Repetti
                May 3 at 7:58












                Aye, this is how I would do it in F#, so it makes sense to do the same here. :)
                – 202_accepted
                May 3 at 11:44




                Aye, this is how I would do it in F#, so it makes sense to do the same here. :)
                – 202_accepted
                May 3 at 11:44










                up vote
                8
                down vote













                With the help of LINQ and some helper methods, you can achieve the same with a lot less repetitive code.



                How do we do it? Well we extract the foreach loop into an iterator which will return the current count of predicate matches:



                private static IEnumerable<int> GetMatchingValues<T>(IEnumerable<T> items, Predicate<T> predicate)

                int count = 0;
                foreach (var item in items)

                if (predicate.Invoke(item))

                yield return ++count;





                Once you have that it's a lot easier to see the pattern, most of those functions are either .Any or .All invocations, except for 1 odd case which really annoys me, perhaps someone smarter can figure it out:



                public static bool CountAtLeast<T>(this IEnumerable<T> items, Predicate<T> predicate, int required)

                return GetMatchingValues(items, predicate).Any(count => count == required);


                public static bool CountAbove<T>(this IEnumerable<T> items, Predicate<T> predicate, int required)

                return GetMatchingValues(items, predicate).Any(count => count > required);


                public static bool CountEqual<T>(this IEnumerable<T> items, Predicate<T> predicate, int required)

                int finalCount = 0;
                foreach (int count in GetMatchingValues(items, predicate))

                finalCount = count;
                if (finalCount > required) break;

                return finalCount == required;


                public static bool CountNotEqual<T>(this IEnumerable<T> items, Predicate<T> predicate, int required)

                return !CountEqual(items, predicate, required);


                public static bool CountBelow<T>(this IEnumerable<T> items, Predicate<T> predicate, int required)

                return !GetMatchingValues(items, predicate).Any(count => count >= required);


                public static bool CountNoMoreThan<T>(this IEnumerable<T> items, Predicate<T> predicate, int required)

                return GetMatchingValues(items, predicate).All(count => count != required);






                share|improve this answer



















                • 2




                  @Flater the iterator does not know when the end is. That's why it returns all the values. If you believe there is a cleaner approach please post an answer or add a short snippet in Fiddle and drop it here. I will be very interested in it.
                  – Denis
                  May 3 at 7:32






                • 1




                  @Flater It is effectively omitting the local variable declaration and it allows us to operate on the predicate matches as a sequence of elements instead of separate integers. It's true that only the last is important but I don't see a way of doing it otherwise, that's why I asked you to add a snippet if you know a better way of doing it.
                  – Denis
                  May 3 at 7:41






                • 1




                  @Flater The iterator is not aware of the magic number. It needs to return 1,2,3,4,5 because the iterator does not know the magic number is 5. The magic number may have been 3.
                  – paparazzo
                  May 3 at 9:36






                • 1




                  @Flater The benefit is less repeated code compared to the OP.
                  – paparazzo
                  May 3 at 10:16






                • 1




                  @Flater would you like to continue the discussion in a chat room? I feel there is some misunderstanding here.
                  – Denis
                  May 3 at 10:54














                up vote
                8
                down vote













                With the help of LINQ and some helper methods, you can achieve the same with a lot less repetitive code.



                How do we do it? Well we extract the foreach loop into an iterator which will return the current count of predicate matches:



                private static IEnumerable<int> GetMatchingValues<T>(IEnumerable<T> items, Predicate<T> predicate)

                int count = 0;
                foreach (var item in items)

                if (predicate.Invoke(item))

                yield return ++count;





                Once you have that it's a lot easier to see the pattern, most of those functions are either .Any or .All invocations, except for 1 odd case which really annoys me, perhaps someone smarter can figure it out:



                public static bool CountAtLeast<T>(this IEnumerable<T> items, Predicate<T> predicate, int required)

                return GetMatchingValues(items, predicate).Any(count => count == required);


                public static bool CountAbove<T>(this IEnumerable<T> items, Predicate<T> predicate, int required)

                return GetMatchingValues(items, predicate).Any(count => count > required);


                public static bool CountEqual<T>(this IEnumerable<T> items, Predicate<T> predicate, int required)

                int finalCount = 0;
                foreach (int count in GetMatchingValues(items, predicate))

                finalCount = count;
                if (finalCount > required) break;

                return finalCount == required;


                public static bool CountNotEqual<T>(this IEnumerable<T> items, Predicate<T> predicate, int required)

                return !CountEqual(items, predicate, required);


                public static bool CountBelow<T>(this IEnumerable<T> items, Predicate<T> predicate, int required)

                return !GetMatchingValues(items, predicate).Any(count => count >= required);


                public static bool CountNoMoreThan<T>(this IEnumerable<T> items, Predicate<T> predicate, int required)

                return GetMatchingValues(items, predicate).All(count => count != required);






                share|improve this answer



















                • 2




                  @Flater the iterator does not know when the end is. That's why it returns all the values. If you believe there is a cleaner approach please post an answer or add a short snippet in Fiddle and drop it here. I will be very interested in it.
                  – Denis
                  May 3 at 7:32






                • 1




                  @Flater It is effectively omitting the local variable declaration and it allows us to operate on the predicate matches as a sequence of elements instead of separate integers. It's true that only the last is important but I don't see a way of doing it otherwise, that's why I asked you to add a snippet if you know a better way of doing it.
                  – Denis
                  May 3 at 7:41






                • 1




                  @Flater The iterator is not aware of the magic number. It needs to return 1,2,3,4,5 because the iterator does not know the magic number is 5. The magic number may have been 3.
                  – paparazzo
                  May 3 at 9:36






                • 1




                  @Flater The benefit is less repeated code compared to the OP.
                  – paparazzo
                  May 3 at 10:16






                • 1




                  @Flater would you like to continue the discussion in a chat room? I feel there is some misunderstanding here.
                  – Denis
                  May 3 at 10:54












                up vote
                8
                down vote










                up vote
                8
                down vote









                With the help of LINQ and some helper methods, you can achieve the same with a lot less repetitive code.



                How do we do it? Well we extract the foreach loop into an iterator which will return the current count of predicate matches:



                private static IEnumerable<int> GetMatchingValues<T>(IEnumerable<T> items, Predicate<T> predicate)

                int count = 0;
                foreach (var item in items)

                if (predicate.Invoke(item))

                yield return ++count;





                Once you have that it's a lot easier to see the pattern, most of those functions are either .Any or .All invocations, except for 1 odd case which really annoys me, perhaps someone smarter can figure it out:



                public static bool CountAtLeast<T>(this IEnumerable<T> items, Predicate<T> predicate, int required)

                return GetMatchingValues(items, predicate).Any(count => count == required);


                public static bool CountAbove<T>(this IEnumerable<T> items, Predicate<T> predicate, int required)

                return GetMatchingValues(items, predicate).Any(count => count > required);


                public static bool CountEqual<T>(this IEnumerable<T> items, Predicate<T> predicate, int required)

                int finalCount = 0;
                foreach (int count in GetMatchingValues(items, predicate))

                finalCount = count;
                if (finalCount > required) break;

                return finalCount == required;


                public static bool CountNotEqual<T>(this IEnumerable<T> items, Predicate<T> predicate, int required)

                return !CountEqual(items, predicate, required);


                public static bool CountBelow<T>(this IEnumerable<T> items, Predicate<T> predicate, int required)

                return !GetMatchingValues(items, predicate).Any(count => count >= required);


                public static bool CountNoMoreThan<T>(this IEnumerable<T> items, Predicate<T> predicate, int required)

                return GetMatchingValues(items, predicate).All(count => count != required);






                share|improve this answer















                With the help of LINQ and some helper methods, you can achieve the same with a lot less repetitive code.



                How do we do it? Well we extract the foreach loop into an iterator which will return the current count of predicate matches:



                private static IEnumerable<int> GetMatchingValues<T>(IEnumerable<T> items, Predicate<T> predicate)

                int count = 0;
                foreach (var item in items)

                if (predicate.Invoke(item))

                yield return ++count;





                Once you have that it's a lot easier to see the pattern, most of those functions are either .Any or .All invocations, except for 1 odd case which really annoys me, perhaps someone smarter can figure it out:



                public static bool CountAtLeast<T>(this IEnumerable<T> items, Predicate<T> predicate, int required)

                return GetMatchingValues(items, predicate).Any(count => count == required);


                public static bool CountAbove<T>(this IEnumerable<T> items, Predicate<T> predicate, int required)

                return GetMatchingValues(items, predicate).Any(count => count > required);


                public static bool CountEqual<T>(this IEnumerable<T> items, Predicate<T> predicate, int required)

                int finalCount = 0;
                foreach (int count in GetMatchingValues(items, predicate))

                finalCount = count;
                if (finalCount > required) break;

                return finalCount == required;


                public static bool CountNotEqual<T>(this IEnumerable<T> items, Predicate<T> predicate, int required)

                return !CountEqual(items, predicate, required);


                public static bool CountBelow<T>(this IEnumerable<T> items, Predicate<T> predicate, int required)

                return !GetMatchingValues(items, predicate).Any(count => count >= required);


                public static bool CountNoMoreThan<T>(this IEnumerable<T> items, Predicate<T> predicate, int required)

                return GetMatchingValues(items, predicate).All(count => count != required);







                share|improve this answer















                share|improve this answer



                share|improve this answer








                edited May 2 at 22:31


























                answered May 2 at 22:25









                Denis

                6,16021453




                6,16021453







                • 2




                  @Flater the iterator does not know when the end is. That's why it returns all the values. If you believe there is a cleaner approach please post an answer or add a short snippet in Fiddle and drop it here. I will be very interested in it.
                  – Denis
                  May 3 at 7:32






                • 1




                  @Flater It is effectively omitting the local variable declaration and it allows us to operate on the predicate matches as a sequence of elements instead of separate integers. It's true that only the last is important but I don't see a way of doing it otherwise, that's why I asked you to add a snippet if you know a better way of doing it.
                  – Denis
                  May 3 at 7:41






                • 1




                  @Flater The iterator is not aware of the magic number. It needs to return 1,2,3,4,5 because the iterator does not know the magic number is 5. The magic number may have been 3.
                  – paparazzo
                  May 3 at 9:36






                • 1




                  @Flater The benefit is less repeated code compared to the OP.
                  – paparazzo
                  May 3 at 10:16






                • 1




                  @Flater would you like to continue the discussion in a chat room? I feel there is some misunderstanding here.
                  – Denis
                  May 3 at 10:54












                • 2




                  @Flater the iterator does not know when the end is. That's why it returns all the values. If you believe there is a cleaner approach please post an answer or add a short snippet in Fiddle and drop it here. I will be very interested in it.
                  – Denis
                  May 3 at 7:32






                • 1




                  @Flater It is effectively omitting the local variable declaration and it allows us to operate on the predicate matches as a sequence of elements instead of separate integers. It's true that only the last is important but I don't see a way of doing it otherwise, that's why I asked you to add a snippet if you know a better way of doing it.
                  – Denis
                  May 3 at 7:41






                • 1




                  @Flater The iterator is not aware of the magic number. It needs to return 1,2,3,4,5 because the iterator does not know the magic number is 5. The magic number may have been 3.
                  – paparazzo
                  May 3 at 9:36






                • 1




                  @Flater The benefit is less repeated code compared to the OP.
                  – paparazzo
                  May 3 at 10:16






                • 1




                  @Flater would you like to continue the discussion in a chat room? I feel there is some misunderstanding here.
                  – Denis
                  May 3 at 10:54







                2




                2




                @Flater the iterator does not know when the end is. That's why it returns all the values. If you believe there is a cleaner approach please post an answer or add a short snippet in Fiddle and drop it here. I will be very interested in it.
                – Denis
                May 3 at 7:32




                @Flater the iterator does not know when the end is. That's why it returns all the values. If you believe there is a cleaner approach please post an answer or add a short snippet in Fiddle and drop it here. I will be very interested in it.
                – Denis
                May 3 at 7:32




                1




                1




                @Flater It is effectively omitting the local variable declaration and it allows us to operate on the predicate matches as a sequence of elements instead of separate integers. It's true that only the last is important but I don't see a way of doing it otherwise, that's why I asked you to add a snippet if you know a better way of doing it.
                – Denis
                May 3 at 7:41




                @Flater It is effectively omitting the local variable declaration and it allows us to operate on the predicate matches as a sequence of elements instead of separate integers. It's true that only the last is important but I don't see a way of doing it otherwise, that's why I asked you to add a snippet if you know a better way of doing it.
                – Denis
                May 3 at 7:41




                1




                1




                @Flater The iterator is not aware of the magic number. It needs to return 1,2,3,4,5 because the iterator does not know the magic number is 5. The magic number may have been 3.
                – paparazzo
                May 3 at 9:36




                @Flater The iterator is not aware of the magic number. It needs to return 1,2,3,4,5 because the iterator does not know the magic number is 5. The magic number may have been 3.
                – paparazzo
                May 3 at 9:36




                1




                1




                @Flater The benefit is less repeated code compared to the OP.
                – paparazzo
                May 3 at 10:16




                @Flater The benefit is less repeated code compared to the OP.
                – paparazzo
                May 3 at 10:16




                1




                1




                @Flater would you like to continue the discussion in a chat room? I feel there is some misunderstanding here.
                – Denis
                May 3 at 10:54




                @Flater would you like to continue the discussion in a chat room? I feel there is some misunderstanding here.
                – Denis
                May 3 at 10:54










                up vote
                7
                down vote













                Two minor recommendations:



                1. Rename items to source to be in-line with how LINQ does it.


                2. Add parameter checking to the beginning of the methods as LINQ does:



                   if (source == null)

                  throw new ArgumentNullException(nameof(source));


                  if (predicate == null)

                  throw new ArgumentNullException(nameof(predicate));



                And it looks solid!



                ETA: Given the other super-cool answers, adding in the magic of C#7, I've refactored a little bit:



                public static class IEnumerableTCountExtensions

                public static bool CountGreaterThanOrEqual<T>(this IEnumerable<T> source, Func<T, bool> predicate, int required) => source == null
                ? throw new ArgumentNullException(nameof(source))
                : (predicate == null
                ? throw new ArgumentNullException(nameof(predicate))
                : source.Where(predicate).Take(required).Count() == required);

                public static bool CountGreaterThan<T>(this IEnumerable<T> source, Func<T, bool> predicate, int required) => source == null
                ? throw new ArgumentNullException(nameof(source))
                : (predicate == null
                ? throw new ArgumentNullException(nameof(predicate))
                : source.Where(predicate).Take(required + 1).Count() > required);

                public static bool CountEqual<T>(this IEnumerable<T> source, Func<T, bool> predicate, int required) => source == null
                ? throw new ArgumentNullException(nameof(source))
                : (predicate == null
                ? throw new ArgumentNullException(nameof(predicate))
                : source.Where(predicate).Take(required + 1).Count() == required);

                public static bool CountNotEqual<T>(this IEnumerable<T> source, Func<T, bool> predicate, int required) => source == null
                ? throw new ArgumentNullException(nameof(source))
                : (predicate == null
                ? throw new ArgumentNullException(nameof(predicate))
                : source.Where(predicate).Take(required + 1).Count() != required);

                public static bool CountLessThan<T>(this IEnumerable<T> source, Func<T, bool> predicate, int required) => source == null
                ? throw new ArgumentNullException(nameof(source))
                : (predicate == null
                ? throw new ArgumentNullException(nameof(predicate))
                : source.Where(predicate).Take(required).Count() < required);

                public static bool CountLessThanOrEqual<T>(this IEnumerable<T> source, Func<T, bool> predicate, int required) => source == null
                ? throw new ArgumentNullException(nameof(source))
                : (predicate == null
                ? throw new ArgumentNullException(nameof(predicate))
                : source.Where(predicate).Take(required + 1).Count() <= required);






                share|improve this answer



















                • 1




                  I know this is just a style preference but I never like using ternary conditional operator for throwing. I prefer to either have the guard clause or have a static guard class that does the checking. Or even better to use code contracts.
                  – CharlesNRice
                  May 3 at 13:32














                up vote
                7
                down vote













                Two minor recommendations:



                1. Rename items to source to be in-line with how LINQ does it.


                2. Add parameter checking to the beginning of the methods as LINQ does:



                   if (source == null)

                  throw new ArgumentNullException(nameof(source));


                  if (predicate == null)

                  throw new ArgumentNullException(nameof(predicate));



                And it looks solid!



                ETA: Given the other super-cool answers, adding in the magic of C#7, I've refactored a little bit:



                public static class IEnumerableTCountExtensions

                public static bool CountGreaterThanOrEqual<T>(this IEnumerable<T> source, Func<T, bool> predicate, int required) => source == null
                ? throw new ArgumentNullException(nameof(source))
                : (predicate == null
                ? throw new ArgumentNullException(nameof(predicate))
                : source.Where(predicate).Take(required).Count() == required);

                public static bool CountGreaterThan<T>(this IEnumerable<T> source, Func<T, bool> predicate, int required) => source == null
                ? throw new ArgumentNullException(nameof(source))
                : (predicate == null
                ? throw new ArgumentNullException(nameof(predicate))
                : source.Where(predicate).Take(required + 1).Count() > required);

                public static bool CountEqual<T>(this IEnumerable<T> source, Func<T, bool> predicate, int required) => source == null
                ? throw new ArgumentNullException(nameof(source))
                : (predicate == null
                ? throw new ArgumentNullException(nameof(predicate))
                : source.Where(predicate).Take(required + 1).Count() == required);

                public static bool CountNotEqual<T>(this IEnumerable<T> source, Func<T, bool> predicate, int required) => source == null
                ? throw new ArgumentNullException(nameof(source))
                : (predicate == null
                ? throw new ArgumentNullException(nameof(predicate))
                : source.Where(predicate).Take(required + 1).Count() != required);

                public static bool CountLessThan<T>(this IEnumerable<T> source, Func<T, bool> predicate, int required) => source == null
                ? throw new ArgumentNullException(nameof(source))
                : (predicate == null
                ? throw new ArgumentNullException(nameof(predicate))
                : source.Where(predicate).Take(required).Count() < required);

                public static bool CountLessThanOrEqual<T>(this IEnumerable<T> source, Func<T, bool> predicate, int required) => source == null
                ? throw new ArgumentNullException(nameof(source))
                : (predicate == null
                ? throw new ArgumentNullException(nameof(predicate))
                : source.Where(predicate).Take(required + 1).Count() <= required);






                share|improve this answer



















                • 1




                  I know this is just a style preference but I never like using ternary conditional operator for throwing. I prefer to either have the guard clause or have a static guard class that does the checking. Or even better to use code contracts.
                  – CharlesNRice
                  May 3 at 13:32












                up vote
                7
                down vote










                up vote
                7
                down vote









                Two minor recommendations:



                1. Rename items to source to be in-line with how LINQ does it.


                2. Add parameter checking to the beginning of the methods as LINQ does:



                   if (source == null)

                  throw new ArgumentNullException(nameof(source));


                  if (predicate == null)

                  throw new ArgumentNullException(nameof(predicate));



                And it looks solid!



                ETA: Given the other super-cool answers, adding in the magic of C#7, I've refactored a little bit:



                public static class IEnumerableTCountExtensions

                public static bool CountGreaterThanOrEqual<T>(this IEnumerable<T> source, Func<T, bool> predicate, int required) => source == null
                ? throw new ArgumentNullException(nameof(source))
                : (predicate == null
                ? throw new ArgumentNullException(nameof(predicate))
                : source.Where(predicate).Take(required).Count() == required);

                public static bool CountGreaterThan<T>(this IEnumerable<T> source, Func<T, bool> predicate, int required) => source == null
                ? throw new ArgumentNullException(nameof(source))
                : (predicate == null
                ? throw new ArgumentNullException(nameof(predicate))
                : source.Where(predicate).Take(required + 1).Count() > required);

                public static bool CountEqual<T>(this IEnumerable<T> source, Func<T, bool> predicate, int required) => source == null
                ? throw new ArgumentNullException(nameof(source))
                : (predicate == null
                ? throw new ArgumentNullException(nameof(predicate))
                : source.Where(predicate).Take(required + 1).Count() == required);

                public static bool CountNotEqual<T>(this IEnumerable<T> source, Func<T, bool> predicate, int required) => source == null
                ? throw new ArgumentNullException(nameof(source))
                : (predicate == null
                ? throw new ArgumentNullException(nameof(predicate))
                : source.Where(predicate).Take(required + 1).Count() != required);

                public static bool CountLessThan<T>(this IEnumerable<T> source, Func<T, bool> predicate, int required) => source == null
                ? throw new ArgumentNullException(nameof(source))
                : (predicate == null
                ? throw new ArgumentNullException(nameof(predicate))
                : source.Where(predicate).Take(required).Count() < required);

                public static bool CountLessThanOrEqual<T>(this IEnumerable<T> source, Func<T, bool> predicate, int required) => source == null
                ? throw new ArgumentNullException(nameof(source))
                : (predicate == null
                ? throw new ArgumentNullException(nameof(predicate))
                : source.Where(predicate).Take(required + 1).Count() <= required);






                share|improve this answer















                Two minor recommendations:



                1. Rename items to source to be in-line with how LINQ does it.


                2. Add parameter checking to the beginning of the methods as LINQ does:



                   if (source == null)

                  throw new ArgumentNullException(nameof(source));


                  if (predicate == null)

                  throw new ArgumentNullException(nameof(predicate));



                And it looks solid!



                ETA: Given the other super-cool answers, adding in the magic of C#7, I've refactored a little bit:



                public static class IEnumerableTCountExtensions

                public static bool CountGreaterThanOrEqual<T>(this IEnumerable<T> source, Func<T, bool> predicate, int required) => source == null
                ? throw new ArgumentNullException(nameof(source))
                : (predicate == null
                ? throw new ArgumentNullException(nameof(predicate))
                : source.Where(predicate).Take(required).Count() == required);

                public static bool CountGreaterThan<T>(this IEnumerable<T> source, Func<T, bool> predicate, int required) => source == null
                ? throw new ArgumentNullException(nameof(source))
                : (predicate == null
                ? throw new ArgumentNullException(nameof(predicate))
                : source.Where(predicate).Take(required + 1).Count() > required);

                public static bool CountEqual<T>(this IEnumerable<T> source, Func<T, bool> predicate, int required) => source == null
                ? throw new ArgumentNullException(nameof(source))
                : (predicate == null
                ? throw new ArgumentNullException(nameof(predicate))
                : source.Where(predicate).Take(required + 1).Count() == required);

                public static bool CountNotEqual<T>(this IEnumerable<T> source, Func<T, bool> predicate, int required) => source == null
                ? throw new ArgumentNullException(nameof(source))
                : (predicate == null
                ? throw new ArgumentNullException(nameof(predicate))
                : source.Where(predicate).Take(required + 1).Count() != required);

                public static bool CountLessThan<T>(this IEnumerable<T> source, Func<T, bool> predicate, int required) => source == null
                ? throw new ArgumentNullException(nameof(source))
                : (predicate == null
                ? throw new ArgumentNullException(nameof(predicate))
                : source.Where(predicate).Take(required).Count() < required);

                public static bool CountLessThanOrEqual<T>(this IEnumerable<T> source, Func<T, bool> predicate, int required) => source == null
                ? throw new ArgumentNullException(nameof(source))
                : (predicate == null
                ? throw new ArgumentNullException(nameof(predicate))
                : source.Where(predicate).Take(required + 1).Count() <= required);







                share|improve this answer















                share|improve this answer



                share|improve this answer








                edited May 3 at 13:27


























                answered May 2 at 21:45









                Jesse C. Slicer

                10.9k2738




                10.9k2738







                • 1




                  I know this is just a style preference but I never like using ternary conditional operator for throwing. I prefer to either have the guard clause or have a static guard class that does the checking. Or even better to use code contracts.
                  – CharlesNRice
                  May 3 at 13:32












                • 1




                  I know this is just a style preference but I never like using ternary conditional operator for throwing. I prefer to either have the guard clause or have a static guard class that does the checking. Or even better to use code contracts.
                  – CharlesNRice
                  May 3 at 13:32







                1




                1




                I know this is just a style preference but I never like using ternary conditional operator for throwing. I prefer to either have the guard clause or have a static guard class that does the checking. Or even better to use code contracts.
                – CharlesNRice
                May 3 at 13:32




                I know this is just a style preference but I never like using ternary conditional operator for throwing. I prefer to either have the guard clause or have a static guard class that does the checking. Or even better to use code contracts.
                – CharlesNRice
                May 3 at 13:32










                up vote
                5
                down vote













                The action which is taken if the if condition is true isn't consitent. Sometimes you return out of the if and sometimes you break out of the loop althougth you could do it the same way.



                E.g



                In CountAbove you break if count > required to return count > required but in CountEqual you return false if count > required and if that if condition is never evaluated to true you return count == required.




                You could use some pre-check to make sure you won't need to iterate at all by soft-casting the IEnumerable<T> items to an ICollection<T>/ICollection and if the soft-cast succeed you can check the Count property.



                You may say but what about the predicate? Well e.g. for CountAbove the Count property of the ICollection<T>/ICollection needs to be at least greater than required like so



                public static bool CountAbove<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

                ICollection<T> collectionOfT = items as ICollection<T>;
                if (collectionOfT != null && collectionOfT.Count <= required) return false;
                ICollection collection = items as ICollection;
                if (collection != null && collection.Count <= required) return false;

                var count = 0;
                foreach (T item in items)

                if (predicate(item))

                count++;
                if (count > required) break;


                return count > required;






                share|improve this answer

























                  up vote
                  5
                  down vote













                  The action which is taken if the if condition is true isn't consitent. Sometimes you return out of the if and sometimes you break out of the loop althougth you could do it the same way.



                  E.g



                  In CountAbove you break if count > required to return count > required but in CountEqual you return false if count > required and if that if condition is never evaluated to true you return count == required.




                  You could use some pre-check to make sure you won't need to iterate at all by soft-casting the IEnumerable<T> items to an ICollection<T>/ICollection and if the soft-cast succeed you can check the Count property.



                  You may say but what about the predicate? Well e.g. for CountAbove the Count property of the ICollection<T>/ICollection needs to be at least greater than required like so



                  public static bool CountAbove<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

                  ICollection<T> collectionOfT = items as ICollection<T>;
                  if (collectionOfT != null && collectionOfT.Count <= required) return false;
                  ICollection collection = items as ICollection;
                  if (collection != null && collection.Count <= required) return false;

                  var count = 0;
                  foreach (T item in items)

                  if (predicate(item))

                  count++;
                  if (count > required) break;


                  return count > required;






                  share|improve this answer























                    up vote
                    5
                    down vote










                    up vote
                    5
                    down vote









                    The action which is taken if the if condition is true isn't consitent. Sometimes you return out of the if and sometimes you break out of the loop althougth you could do it the same way.



                    E.g



                    In CountAbove you break if count > required to return count > required but in CountEqual you return false if count > required and if that if condition is never evaluated to true you return count == required.




                    You could use some pre-check to make sure you won't need to iterate at all by soft-casting the IEnumerable<T> items to an ICollection<T>/ICollection and if the soft-cast succeed you can check the Count property.



                    You may say but what about the predicate? Well e.g. for CountAbove the Count property of the ICollection<T>/ICollection needs to be at least greater than required like so



                    public static bool CountAbove<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

                    ICollection<T> collectionOfT = items as ICollection<T>;
                    if (collectionOfT != null && collectionOfT.Count <= required) return false;
                    ICollection collection = items as ICollection;
                    if (collection != null && collection.Count <= required) return false;

                    var count = 0;
                    foreach (T item in items)

                    if (predicate(item))

                    count++;
                    if (count > required) break;


                    return count > required;






                    share|improve this answer













                    The action which is taken if the if condition is true isn't consitent. Sometimes you return out of the if and sometimes you break out of the loop althougth you could do it the same way.



                    E.g



                    In CountAbove you break if count > required to return count > required but in CountEqual you return false if count > required and if that if condition is never evaluated to true you return count == required.




                    You could use some pre-check to make sure you won't need to iterate at all by soft-casting the IEnumerable<T> items to an ICollection<T>/ICollection and if the soft-cast succeed you can check the Count property.



                    You may say but what about the predicate? Well e.g. for CountAbove the Count property of the ICollection<T>/ICollection needs to be at least greater than required like so



                    public static bool CountAbove<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

                    ICollection<T> collectionOfT = items as ICollection<T>;
                    if (collectionOfT != null && collectionOfT.Count <= required) return false;
                    ICollection collection = items as ICollection;
                    if (collection != null && collection.Count <= required) return false;

                    var count = 0;
                    foreach (T item in items)

                    if (predicate(item))

                    count++;
                    if (count > required) break;


                    return count > required;







                    share|improve this answer













                    share|improve this answer



                    share|improve this answer











                    answered May 3 at 6:41









                    Heslacher

                    43.9k359152




                    43.9k359152




















                        up vote
                        5
                        down vote













                        This is a variation on Denis' answer. While his answer works, it is returning a progressive count (1,2,3,4,5) for no good reason. In the end, you're only interested in the last number (5) that is returned, so there is no point to wrapping the count in an IEnumerable.



                        Furthermore, because of the combined use of logical inversions, Any and All, Denis' code (while it does work) becomes quite hard to quickly read through. There is a difference between e.g. !myList.All(x => x == myValue) and myList.All(x => x != myValue), but the distinction is hard to miss here.



                        Comparatively, the distinction between myCount == myValue and myCount != myValue is much easier to parse at a glance, which is why I think my answer is better from a readability standpoint (even though it is functionally equivalent, which I do concede).




                        The counting algorithm



                        private static int CountMatchesUpTo<T>(IEnumerable<T> items, Predicate<T> predicate, int boundary)

                        int count = 0;
                        foreach (var item in items)

                        if (predicate.Invoke(item))

                        count++;


                        if(count == boundary)

                        break;



                        return count;



                        There are two possible ways that the return statement can be reached:



                        • Because the foreach completed. This happens if you have less than boundary matches in your list, since you keep looking for matches up to the boundary.

                        • Because the boundary was reached. At this point, the foreach is forcefully broken out of, and the count (equal to boundary) is returned. The remaining items of the list were never iterated over.


                        The wrapper methods



                        The implementation of most of the other methods is relatively easy to do.



                        Notice that in some cases, I use required + 1 as the upper bound. This is relevant in cases where you want to distinguish between a match count that is either equal to or greater than the boundary.



                        Assuming you're using a boundary of 5, you then instruct the counting method to look for 6 items.



                        • If it returns 6, then you know that there are more than 5 matches.

                        • If it returns 5, then you know that there are exactly 5 matches (the same applies for a smaller return value).

                        This takes care of the "upper" short circuit. The "lower" short circuit is already taken care of as you will receive a lower number if not enough matches were found.



                        public static bool CountEqual<T>(this IEnumerable<T> items, Predicate<T> predicate, int required)

                        return CountMatchesUpTo(items, predicate, required + 1) == required;


                        public static bool CountNotEqual<T>(this IEnumerable<T> items, Predicate<T> predicate, int required)

                        return CountMatchesUpTo(items, predicate, required + 1) != required;


                        public static bool CountAbove<T>(this IEnumerable<T> items, Predicate<T> predicate, int required)

                        return CountMatchesUpTo(items, predicate, required + 1) > required;


                        public static bool CountAtLeast<T>(this IEnumerable<T> items, Predicate<T> predicate, int required)

                        return CountMatchesUpTo(items, predicate, required) == required;




                        public static bool CountBelow<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

                        var count = 0;
                        foreach (T item in items)

                        if (predicate(item))

                        count++;
                        if (count >= required) return false;


                        return count < required;


                        public static bool CountNoMoreThan<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

                        var count = 0;
                        foreach (T item in items)

                        if (predicate(item))

                        count++;
                        if (count == required) return false;


                        return count <= required;



                        There are two things to notice here:



                        1 - In one method, you do if (count >= required) return false; , and in the other, you do if (count == required) return false; . Since count is incrementing one at a time, count >= required will evaluate to true because it count is equal to required. Count will never be greater than required since you exit the method when it already equals it.



                        2 - CountNoMoreThan is also unintuitive for another reason: you do if (count == required) return false; and then return count <= required;.

                        The return statement will never find a case where count equals required, since you've already explicitly returned false when you find an equality. The return statement can therefore be refactored to return count < required;.



                        Combining the findings of 1 and 2, this means that CountBelow and CountNoMoreThan are currently functionally equivalent methods. There's no point to having both methods.



                        From the method names, I surmise that the difference between the two is < or <=. Using my refactored approach, the difference is easy to implement:



                        public static bool CountNoMoreThan<T>(this IEnumerable<T> items, Predicate<T> predicate, int required)

                        return CountMatchesUpTo(items, predicate, required + 1) <= required;



                        Note that we again use required+1, to allow for the count method to tell us if there are more matches than the boundary.



                        public static bool CountBelow<T>(this IEnumerable<T> items, Predicate<T> predicate, int required)

                        return CountMatchesUpTo(items, predicate, required) < required;




                        Footnote



                        As it stands, all the listed methods are merely an enumeration of int comparisons: ==, !=, >, >=, <, <=.



                        There is little point to doing this. You can simply make CountMatchesUpTo a publically accessible method, and rely on your caller to do their own evaluation.



                        If you're already expecting your caller to know which method to use, that means that they know which evaluation they want to take place. There is no added benefit from putting it in an additional method layer.



                        If you're doing more cumbersome logic (e.g. checking if two datetimes overlap), that is relevant to put into a method, as it would be cumbersome to write every time. But your current evaluations are not complex enough to warrant their own method layer.



                        The issue here is that your additional layer is an additional place for bugs to sneak into the code. And it already did, as I found a bug in CountNoMoreThan. If uncaught, external consumers of your methods would be hunting for bugs in their own code, unaware that your method is simply not doing what its name advertises.




                        Update



                        Update is not correct. See below.



                        Two of your tests appear to be incorrect:



                        Console.WriteLine("F? " + things.CountEqual(x => x <= 5, 2));
                        Console.WriteLine("T? " + things.CountNotEqual(x => x <= 5, 2));


                        Since you set the boundary at 2, the "count up to" algorithm will logically stop iterating over the collection once it reaches a count of 2.



                        This means that things.CountEqual(x => x <= 5, 2) will return true, and things.CountNotEqual(x => x <= 5, 2) will return false.



                        Your test seemingly expects that the counting method will still count 5 elements; which violates the algorithm (as it should stop after the defined boundary, which in this case is 2).



                        It's an easy mistake to make; one that I had initially glossed over too, as I understood what you were trying to test. But the expected outcome of these two tests should be inverted; otherwise it would violate your proposed algorithm.



                        Update to the update



                        The requirements were clarified by OP in chat. The above code has been altered to reflect that.






                        share|improve this answer



















                        • 2




                          As far as I like your comments (+1) I always find this argument very weak: The issue here is that your additional layer is an additional place for bugs to sneak into the code. - I treat creating convenience extensions (or any other resusable code) always a good thing because I'm a lazy engineer ;-) sure, there might be some bugs (usually at the beginning) but you know where to find them and they are easier to test and to fix and what's even more imporatnt, you're doing this only once and when you're done, you never have to implement this logic again so it's actually a good thing.
                          – t3chb0t
                          May 3 at 10:30











                        • @t3chb0t: I'm all for convenience extensions (as I mentioned for datetime overlap). However, the current methods are wrapping the most elementary of comparison operators. There is a reasonability argument here; if the method doesn't shorten the code and choosing the correct method requires the same level of knowledge as doing the comparison yourself; there's no convenience from having the method. Comparatively, Datetime overlap comparison is a reasonable convenience, because it's cumbersome to always write the multiple comparison evaluations needed to correctly check for an overlap.
                          – Flater
                          May 3 at 10:36











                        • For us outsiders/readers, it's always difficult to tell whether something is useful/convenient or not as we might not have the need for it yet but I guess OP might have already be using similar code multiple times so in his projects this is a convenience. Another such example could be my extensions for testing common interfaces. Not much feedback received, probalby because nobody is doing this but I'm using them in many projects; it's relative :-]
                          – t3chb0t
                          May 3 at 10:49











                        • CountEqual and CountNotEqual don't quite work, at least the way it's posted here, you should run the tests OP has provided.
                          – Denis
                          May 3 at 10:51










                        • @Flater those 2 tests specifically Console.WriteLine("F? " + things.CountEqual(x => x <= 5, 2));, Console.WriteLine("T? " + things.CountNotEqual(x => x <= 5, 2));.
                          – Denis
                          May 3 at 11:00















                        up vote
                        5
                        down vote













                        This is a variation on Denis' answer. While his answer works, it is returning a progressive count (1,2,3,4,5) for no good reason. In the end, you're only interested in the last number (5) that is returned, so there is no point to wrapping the count in an IEnumerable.



                        Furthermore, because of the combined use of logical inversions, Any and All, Denis' code (while it does work) becomes quite hard to quickly read through. There is a difference between e.g. !myList.All(x => x == myValue) and myList.All(x => x != myValue), but the distinction is hard to miss here.



                        Comparatively, the distinction between myCount == myValue and myCount != myValue is much easier to parse at a glance, which is why I think my answer is better from a readability standpoint (even though it is functionally equivalent, which I do concede).




                        The counting algorithm



                        private static int CountMatchesUpTo<T>(IEnumerable<T> items, Predicate<T> predicate, int boundary)

                        int count = 0;
                        foreach (var item in items)

                        if (predicate.Invoke(item))

                        count++;


                        if(count == boundary)

                        break;



                        return count;



                        There are two possible ways that the return statement can be reached:



                        • Because the foreach completed. This happens if you have less than boundary matches in your list, since you keep looking for matches up to the boundary.

                        • Because the boundary was reached. At this point, the foreach is forcefully broken out of, and the count (equal to boundary) is returned. The remaining items of the list were never iterated over.


                        The wrapper methods



                        The implementation of most of the other methods is relatively easy to do.



                        Notice that in some cases, I use required + 1 as the upper bound. This is relevant in cases where you want to distinguish between a match count that is either equal to or greater than the boundary.



                        Assuming you're using a boundary of 5, you then instruct the counting method to look for 6 items.



                        • If it returns 6, then you know that there are more than 5 matches.

                        • If it returns 5, then you know that there are exactly 5 matches (the same applies for a smaller return value).

                        This takes care of the "upper" short circuit. The "lower" short circuit is already taken care of as you will receive a lower number if not enough matches were found.



                        public static bool CountEqual<T>(this IEnumerable<T> items, Predicate<T> predicate, int required)

                        return CountMatchesUpTo(items, predicate, required + 1) == required;


                        public static bool CountNotEqual<T>(this IEnumerable<T> items, Predicate<T> predicate, int required)

                        return CountMatchesUpTo(items, predicate, required + 1) != required;


                        public static bool CountAbove<T>(this IEnumerable<T> items, Predicate<T> predicate, int required)

                        return CountMatchesUpTo(items, predicate, required + 1) > required;


                        public static bool CountAtLeast<T>(this IEnumerable<T> items, Predicate<T> predicate, int required)

                        return CountMatchesUpTo(items, predicate, required) == required;




                        public static bool CountBelow<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

                        var count = 0;
                        foreach (T item in items)

                        if (predicate(item))

                        count++;
                        if (count >= required) return false;


                        return count < required;


                        public static bool CountNoMoreThan<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

                        var count = 0;
                        foreach (T item in items)

                        if (predicate(item))

                        count++;
                        if (count == required) return false;


                        return count <= required;



                        There are two things to notice here:



                        1 - In one method, you do if (count >= required) return false; , and in the other, you do if (count == required) return false; . Since count is incrementing one at a time, count >= required will evaluate to true because it count is equal to required. Count will never be greater than required since you exit the method when it already equals it.



                        2 - CountNoMoreThan is also unintuitive for another reason: you do if (count == required) return false; and then return count <= required;.

                        The return statement will never find a case where count equals required, since you've already explicitly returned false when you find an equality. The return statement can therefore be refactored to return count < required;.



                        Combining the findings of 1 and 2, this means that CountBelow and CountNoMoreThan are currently functionally equivalent methods. There's no point to having both methods.



                        From the method names, I surmise that the difference between the two is < or <=. Using my refactored approach, the difference is easy to implement:



                        public static bool CountNoMoreThan<T>(this IEnumerable<T> items, Predicate<T> predicate, int required)

                        return CountMatchesUpTo(items, predicate, required + 1) <= required;



                        Note that we again use required+1, to allow for the count method to tell us if there are more matches than the boundary.



                        public static bool CountBelow<T>(this IEnumerable<T> items, Predicate<T> predicate, int required)

                        return CountMatchesUpTo(items, predicate, required) < required;




                        Footnote



                        As it stands, all the listed methods are merely an enumeration of int comparisons: ==, !=, >, >=, <, <=.



                        There is little point to doing this. You can simply make CountMatchesUpTo a publically accessible method, and rely on your caller to do their own evaluation.



                        If you're already expecting your caller to know which method to use, that means that they know which evaluation they want to take place. There is no added benefit from putting it in an additional method layer.



                        If you're doing more cumbersome logic (e.g. checking if two datetimes overlap), that is relevant to put into a method, as it would be cumbersome to write every time. But your current evaluations are not complex enough to warrant their own method layer.



                        The issue here is that your additional layer is an additional place for bugs to sneak into the code. And it already did, as I found a bug in CountNoMoreThan. If uncaught, external consumers of your methods would be hunting for bugs in their own code, unaware that your method is simply not doing what its name advertises.




                        Update



                        Update is not correct. See below.



                        Two of your tests appear to be incorrect:



                        Console.WriteLine("F? " + things.CountEqual(x => x <= 5, 2));
                        Console.WriteLine("T? " + things.CountNotEqual(x => x <= 5, 2));


                        Since you set the boundary at 2, the "count up to" algorithm will logically stop iterating over the collection once it reaches a count of 2.



                        This means that things.CountEqual(x => x <= 5, 2) will return true, and things.CountNotEqual(x => x <= 5, 2) will return false.



                        Your test seemingly expects that the counting method will still count 5 elements; which violates the algorithm (as it should stop after the defined boundary, which in this case is 2).



                        It's an easy mistake to make; one that I had initially glossed over too, as I understood what you were trying to test. But the expected outcome of these two tests should be inverted; otherwise it would violate your proposed algorithm.



                        Update to the update



                        The requirements were clarified by OP in chat. The above code has been altered to reflect that.






                        share|improve this answer



















                        • 2




                          As far as I like your comments (+1) I always find this argument very weak: The issue here is that your additional layer is an additional place for bugs to sneak into the code. - I treat creating convenience extensions (or any other resusable code) always a good thing because I'm a lazy engineer ;-) sure, there might be some bugs (usually at the beginning) but you know where to find them and they are easier to test and to fix and what's even more imporatnt, you're doing this only once and when you're done, you never have to implement this logic again so it's actually a good thing.
                          – t3chb0t
                          May 3 at 10:30











                        • @t3chb0t: I'm all for convenience extensions (as I mentioned for datetime overlap). However, the current methods are wrapping the most elementary of comparison operators. There is a reasonability argument here; if the method doesn't shorten the code and choosing the correct method requires the same level of knowledge as doing the comparison yourself; there's no convenience from having the method. Comparatively, Datetime overlap comparison is a reasonable convenience, because it's cumbersome to always write the multiple comparison evaluations needed to correctly check for an overlap.
                          – Flater
                          May 3 at 10:36











                        • For us outsiders/readers, it's always difficult to tell whether something is useful/convenient or not as we might not have the need for it yet but I guess OP might have already be using similar code multiple times so in his projects this is a convenience. Another such example could be my extensions for testing common interfaces. Not much feedback received, probalby because nobody is doing this but I'm using them in many projects; it's relative :-]
                          – t3chb0t
                          May 3 at 10:49











                        • CountEqual and CountNotEqual don't quite work, at least the way it's posted here, you should run the tests OP has provided.
                          – Denis
                          May 3 at 10:51










                        • @Flater those 2 tests specifically Console.WriteLine("F? " + things.CountEqual(x => x <= 5, 2));, Console.WriteLine("T? " + things.CountNotEqual(x => x <= 5, 2));.
                          – Denis
                          May 3 at 11:00













                        up vote
                        5
                        down vote










                        up vote
                        5
                        down vote









                        This is a variation on Denis' answer. While his answer works, it is returning a progressive count (1,2,3,4,5) for no good reason. In the end, you're only interested in the last number (5) that is returned, so there is no point to wrapping the count in an IEnumerable.



                        Furthermore, because of the combined use of logical inversions, Any and All, Denis' code (while it does work) becomes quite hard to quickly read through. There is a difference between e.g. !myList.All(x => x == myValue) and myList.All(x => x != myValue), but the distinction is hard to miss here.



                        Comparatively, the distinction between myCount == myValue and myCount != myValue is much easier to parse at a glance, which is why I think my answer is better from a readability standpoint (even though it is functionally equivalent, which I do concede).




                        The counting algorithm



                        private static int CountMatchesUpTo<T>(IEnumerable<T> items, Predicate<T> predicate, int boundary)

                        int count = 0;
                        foreach (var item in items)

                        if (predicate.Invoke(item))

                        count++;


                        if(count == boundary)

                        break;



                        return count;



                        There are two possible ways that the return statement can be reached:



                        • Because the foreach completed. This happens if you have less than boundary matches in your list, since you keep looking for matches up to the boundary.

                        • Because the boundary was reached. At this point, the foreach is forcefully broken out of, and the count (equal to boundary) is returned. The remaining items of the list were never iterated over.


                        The wrapper methods



                        The implementation of most of the other methods is relatively easy to do.



                        Notice that in some cases, I use required + 1 as the upper bound. This is relevant in cases where you want to distinguish between a match count that is either equal to or greater than the boundary.



                        Assuming you're using a boundary of 5, you then instruct the counting method to look for 6 items.



                        • If it returns 6, then you know that there are more than 5 matches.

                        • If it returns 5, then you know that there are exactly 5 matches (the same applies for a smaller return value).

                        This takes care of the "upper" short circuit. The "lower" short circuit is already taken care of as you will receive a lower number if not enough matches were found.



                        public static bool CountEqual<T>(this IEnumerable<T> items, Predicate<T> predicate, int required)

                        return CountMatchesUpTo(items, predicate, required + 1) == required;


                        public static bool CountNotEqual<T>(this IEnumerable<T> items, Predicate<T> predicate, int required)

                        return CountMatchesUpTo(items, predicate, required + 1) != required;


                        public static bool CountAbove<T>(this IEnumerable<T> items, Predicate<T> predicate, int required)

                        return CountMatchesUpTo(items, predicate, required + 1) > required;


                        public static bool CountAtLeast<T>(this IEnumerable<T> items, Predicate<T> predicate, int required)

                        return CountMatchesUpTo(items, predicate, required) == required;




                        public static bool CountBelow<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

                        var count = 0;
                        foreach (T item in items)

                        if (predicate(item))

                        count++;
                        if (count >= required) return false;


                        return count < required;


                        public static bool CountNoMoreThan<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

                        var count = 0;
                        foreach (T item in items)

                        if (predicate(item))

                        count++;
                        if (count == required) return false;


                        return count <= required;



                        There are two things to notice here:



                        1 - In one method, you do if (count >= required) return false; , and in the other, you do if (count == required) return false; . Since count is incrementing one at a time, count >= required will evaluate to true because it count is equal to required. Count will never be greater than required since you exit the method when it already equals it.



                        2 - CountNoMoreThan is also unintuitive for another reason: you do if (count == required) return false; and then return count <= required;.

                        The return statement will never find a case where count equals required, since you've already explicitly returned false when you find an equality. The return statement can therefore be refactored to return count < required;.



                        Combining the findings of 1 and 2, this means that CountBelow and CountNoMoreThan are currently functionally equivalent methods. There's no point to having both methods.



                        From the method names, I surmise that the difference between the two is < or <=. Using my refactored approach, the difference is easy to implement:



                        public static bool CountNoMoreThan<T>(this IEnumerable<T> items, Predicate<T> predicate, int required)

                        return CountMatchesUpTo(items, predicate, required + 1) <= required;



                        Note that we again use required+1, to allow for the count method to tell us if there are more matches than the boundary.



                        public static bool CountBelow<T>(this IEnumerable<T> items, Predicate<T> predicate, int required)

                        return CountMatchesUpTo(items, predicate, required) < required;




                        Footnote



                        As it stands, all the listed methods are merely an enumeration of int comparisons: ==, !=, >, >=, <, <=.



                        There is little point to doing this. You can simply make CountMatchesUpTo a publically accessible method, and rely on your caller to do their own evaluation.



                        If you're already expecting your caller to know which method to use, that means that they know which evaluation they want to take place. There is no added benefit from putting it in an additional method layer.



                        If you're doing more cumbersome logic (e.g. checking if two datetimes overlap), that is relevant to put into a method, as it would be cumbersome to write every time. But your current evaluations are not complex enough to warrant their own method layer.



                        The issue here is that your additional layer is an additional place for bugs to sneak into the code. And it already did, as I found a bug in CountNoMoreThan. If uncaught, external consumers of your methods would be hunting for bugs in their own code, unaware that your method is simply not doing what its name advertises.




                        Update



                        Update is not correct. See below.



                        Two of your tests appear to be incorrect:



                        Console.WriteLine("F? " + things.CountEqual(x => x <= 5, 2));
                        Console.WriteLine("T? " + things.CountNotEqual(x => x <= 5, 2));


                        Since you set the boundary at 2, the "count up to" algorithm will logically stop iterating over the collection once it reaches a count of 2.



                        This means that things.CountEqual(x => x <= 5, 2) will return true, and things.CountNotEqual(x => x <= 5, 2) will return false.



                        Your test seemingly expects that the counting method will still count 5 elements; which violates the algorithm (as it should stop after the defined boundary, which in this case is 2).



                        It's an easy mistake to make; one that I had initially glossed over too, as I understood what you were trying to test. But the expected outcome of these two tests should be inverted; otherwise it would violate your proposed algorithm.



                        Update to the update



                        The requirements were clarified by OP in chat. The above code has been altered to reflect that.






                        share|improve this answer















                        This is a variation on Denis' answer. While his answer works, it is returning a progressive count (1,2,3,4,5) for no good reason. In the end, you're only interested in the last number (5) that is returned, so there is no point to wrapping the count in an IEnumerable.



                        Furthermore, because of the combined use of logical inversions, Any and All, Denis' code (while it does work) becomes quite hard to quickly read through. There is a difference between e.g. !myList.All(x => x == myValue) and myList.All(x => x != myValue), but the distinction is hard to miss here.



                        Comparatively, the distinction between myCount == myValue and myCount != myValue is much easier to parse at a glance, which is why I think my answer is better from a readability standpoint (even though it is functionally equivalent, which I do concede).




                        The counting algorithm



                        private static int CountMatchesUpTo<T>(IEnumerable<T> items, Predicate<T> predicate, int boundary)

                        int count = 0;
                        foreach (var item in items)

                        if (predicate.Invoke(item))

                        count++;


                        if(count == boundary)

                        break;



                        return count;



                        There are two possible ways that the return statement can be reached:



                        • Because the foreach completed. This happens if you have less than boundary matches in your list, since you keep looking for matches up to the boundary.

                        • Because the boundary was reached. At this point, the foreach is forcefully broken out of, and the count (equal to boundary) is returned. The remaining items of the list were never iterated over.


                        The wrapper methods



                        The implementation of most of the other methods is relatively easy to do.



                        Notice that in some cases, I use required + 1 as the upper bound. This is relevant in cases where you want to distinguish between a match count that is either equal to or greater than the boundary.



                        Assuming you're using a boundary of 5, you then instruct the counting method to look for 6 items.



                        • If it returns 6, then you know that there are more than 5 matches.

                        • If it returns 5, then you know that there are exactly 5 matches (the same applies for a smaller return value).

                        This takes care of the "upper" short circuit. The "lower" short circuit is already taken care of as you will receive a lower number if not enough matches were found.



                        public static bool CountEqual<T>(this IEnumerable<T> items, Predicate<T> predicate, int required)

                        return CountMatchesUpTo(items, predicate, required + 1) == required;


                        public static bool CountNotEqual<T>(this IEnumerable<T> items, Predicate<T> predicate, int required)

                        return CountMatchesUpTo(items, predicate, required + 1) != required;


                        public static bool CountAbove<T>(this IEnumerable<T> items, Predicate<T> predicate, int required)

                        return CountMatchesUpTo(items, predicate, required + 1) > required;


                        public static bool CountAtLeast<T>(this IEnumerable<T> items, Predicate<T> predicate, int required)

                        return CountMatchesUpTo(items, predicate, required) == required;




                        public static bool CountBelow<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

                        var count = 0;
                        foreach (T item in items)

                        if (predicate(item))

                        count++;
                        if (count >= required) return false;


                        return count < required;


                        public static bool CountNoMoreThan<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

                        var count = 0;
                        foreach (T item in items)

                        if (predicate(item))

                        count++;
                        if (count == required) return false;


                        return count <= required;



                        There are two things to notice here:



                        1 - In one method, you do if (count >= required) return false; , and in the other, you do if (count == required) return false; . Since count is incrementing one at a time, count >= required will evaluate to true because it count is equal to required. Count will never be greater than required since you exit the method when it already equals it.



                        2 - CountNoMoreThan is also unintuitive for another reason: you do if (count == required) return false; and then return count <= required;.

                        The return statement will never find a case where count equals required, since you've already explicitly returned false when you find an equality. The return statement can therefore be refactored to return count < required;.



                        Combining the findings of 1 and 2, this means that CountBelow and CountNoMoreThan are currently functionally equivalent methods. There's no point to having both methods.



                        From the method names, I surmise that the difference between the two is < or <=. Using my refactored approach, the difference is easy to implement:



                        public static bool CountNoMoreThan<T>(this IEnumerable<T> items, Predicate<T> predicate, int required)

                        return CountMatchesUpTo(items, predicate, required + 1) <= required;



                        Note that we again use required+1, to allow for the count method to tell us if there are more matches than the boundary.



                        public static bool CountBelow<T>(this IEnumerable<T> items, Predicate<T> predicate, int required)

                        return CountMatchesUpTo(items, predicate, required) < required;




                        Footnote



                        As it stands, all the listed methods are merely an enumeration of int comparisons: ==, !=, >, >=, <, <=.



                        There is little point to doing this. You can simply make CountMatchesUpTo a publically accessible method, and rely on your caller to do their own evaluation.



                        If you're already expecting your caller to know which method to use, that means that they know which evaluation they want to take place. There is no added benefit from putting it in an additional method layer.



                        If you're doing more cumbersome logic (e.g. checking if two datetimes overlap), that is relevant to put into a method, as it would be cumbersome to write every time. But your current evaluations are not complex enough to warrant their own method layer.



                        The issue here is that your additional layer is an additional place for bugs to sneak into the code. And it already did, as I found a bug in CountNoMoreThan. If uncaught, external consumers of your methods would be hunting for bugs in their own code, unaware that your method is simply not doing what its name advertises.




                        Update



                        Update is not correct. See below.



                        Two of your tests appear to be incorrect:



                        Console.WriteLine("F? " + things.CountEqual(x => x <= 5, 2));
                        Console.WriteLine("T? " + things.CountNotEqual(x => x <= 5, 2));


                        Since you set the boundary at 2, the "count up to" algorithm will logically stop iterating over the collection once it reaches a count of 2.



                        This means that things.CountEqual(x => x <= 5, 2) will return true, and things.CountNotEqual(x => x <= 5, 2) will return false.



                        Your test seemingly expects that the counting method will still count 5 elements; which violates the algorithm (as it should stop after the defined boundary, which in this case is 2).



                        It's an easy mistake to make; one that I had initially glossed over too, as I understood what you were trying to test. But the expected outcome of these two tests should be inverted; otherwise it would violate your proposed algorithm.



                        Update to the update



                        The requirements were clarified by OP in chat. The above code has been altered to reflect that.







                        share|improve this answer















                        share|improve this answer



                        share|improve this answer








                        edited May 3 at 11:59


























                        answered May 3 at 10:20









                        Flater

                        2,645718




                        2,645718







                        • 2




                          As far as I like your comments (+1) I always find this argument very weak: The issue here is that your additional layer is an additional place for bugs to sneak into the code. - I treat creating convenience extensions (or any other resusable code) always a good thing because I'm a lazy engineer ;-) sure, there might be some bugs (usually at the beginning) but you know where to find them and they are easier to test and to fix and what's even more imporatnt, you're doing this only once and when you're done, you never have to implement this logic again so it's actually a good thing.
                          – t3chb0t
                          May 3 at 10:30











                        • @t3chb0t: I'm all for convenience extensions (as I mentioned for datetime overlap). However, the current methods are wrapping the most elementary of comparison operators. There is a reasonability argument here; if the method doesn't shorten the code and choosing the correct method requires the same level of knowledge as doing the comparison yourself; there's no convenience from having the method. Comparatively, Datetime overlap comparison is a reasonable convenience, because it's cumbersome to always write the multiple comparison evaluations needed to correctly check for an overlap.
                          – Flater
                          May 3 at 10:36











                        • For us outsiders/readers, it's always difficult to tell whether something is useful/convenient or not as we might not have the need for it yet but I guess OP might have already be using similar code multiple times so in his projects this is a convenience. Another such example could be my extensions for testing common interfaces. Not much feedback received, probalby because nobody is doing this but I'm using them in many projects; it's relative :-]
                          – t3chb0t
                          May 3 at 10:49











                        • CountEqual and CountNotEqual don't quite work, at least the way it's posted here, you should run the tests OP has provided.
                          – Denis
                          May 3 at 10:51










                        • @Flater those 2 tests specifically Console.WriteLine("F? " + things.CountEqual(x => x <= 5, 2));, Console.WriteLine("T? " + things.CountNotEqual(x => x <= 5, 2));.
                          – Denis
                          May 3 at 11:00













                        • 2




                          As far as I like your comments (+1) I always find this argument very weak: The issue here is that your additional layer is an additional place for bugs to sneak into the code. - I treat creating convenience extensions (or any other resusable code) always a good thing because I'm a lazy engineer ;-) sure, there might be some bugs (usually at the beginning) but you know where to find them and they are easier to test and to fix and what's even more imporatnt, you're doing this only once and when you're done, you never have to implement this logic again so it's actually a good thing.
                          – t3chb0t
                          May 3 at 10:30











                        • @t3chb0t: I'm all for convenience extensions (as I mentioned for datetime overlap). However, the current methods are wrapping the most elementary of comparison operators. There is a reasonability argument here; if the method doesn't shorten the code and choosing the correct method requires the same level of knowledge as doing the comparison yourself; there's no convenience from having the method. Comparatively, Datetime overlap comparison is a reasonable convenience, because it's cumbersome to always write the multiple comparison evaluations needed to correctly check for an overlap.
                          – Flater
                          May 3 at 10:36











                        • For us outsiders/readers, it's always difficult to tell whether something is useful/convenient or not as we might not have the need for it yet but I guess OP might have already be using similar code multiple times so in his projects this is a convenience. Another such example could be my extensions for testing common interfaces. Not much feedback received, probalby because nobody is doing this but I'm using them in many projects; it's relative :-]
                          – t3chb0t
                          May 3 at 10:49











                        • CountEqual and CountNotEqual don't quite work, at least the way it's posted here, you should run the tests OP has provided.
                          – Denis
                          May 3 at 10:51










                        • @Flater those 2 tests specifically Console.WriteLine("F? " + things.CountEqual(x => x <= 5, 2));, Console.WriteLine("T? " + things.CountNotEqual(x => x <= 5, 2));.
                          – Denis
                          May 3 at 11:00








                        2




                        2




                        As far as I like your comments (+1) I always find this argument very weak: The issue here is that your additional layer is an additional place for bugs to sneak into the code. - I treat creating convenience extensions (or any other resusable code) always a good thing because I'm a lazy engineer ;-) sure, there might be some bugs (usually at the beginning) but you know where to find them and they are easier to test and to fix and what's even more imporatnt, you're doing this only once and when you're done, you never have to implement this logic again so it's actually a good thing.
                        – t3chb0t
                        May 3 at 10:30





                        As far as I like your comments (+1) I always find this argument very weak: The issue here is that your additional layer is an additional place for bugs to sneak into the code. - I treat creating convenience extensions (or any other resusable code) always a good thing because I'm a lazy engineer ;-) sure, there might be some bugs (usually at the beginning) but you know where to find them and they are easier to test and to fix and what's even more imporatnt, you're doing this only once and when you're done, you never have to implement this logic again so it's actually a good thing.
                        – t3chb0t
                        May 3 at 10:30













                        @t3chb0t: I'm all for convenience extensions (as I mentioned for datetime overlap). However, the current methods are wrapping the most elementary of comparison operators. There is a reasonability argument here; if the method doesn't shorten the code and choosing the correct method requires the same level of knowledge as doing the comparison yourself; there's no convenience from having the method. Comparatively, Datetime overlap comparison is a reasonable convenience, because it's cumbersome to always write the multiple comparison evaluations needed to correctly check for an overlap.
                        – Flater
                        May 3 at 10:36





                        @t3chb0t: I'm all for convenience extensions (as I mentioned for datetime overlap). However, the current methods are wrapping the most elementary of comparison operators. There is a reasonability argument here; if the method doesn't shorten the code and choosing the correct method requires the same level of knowledge as doing the comparison yourself; there's no convenience from having the method. Comparatively, Datetime overlap comparison is a reasonable convenience, because it's cumbersome to always write the multiple comparison evaluations needed to correctly check for an overlap.
                        – Flater
                        May 3 at 10:36













                        For us outsiders/readers, it's always difficult to tell whether something is useful/convenient or not as we might not have the need for it yet but I guess OP might have already be using similar code multiple times so in his projects this is a convenience. Another such example could be my extensions for testing common interfaces. Not much feedback received, probalby because nobody is doing this but I'm using them in many projects; it's relative :-]
                        – t3chb0t
                        May 3 at 10:49





                        For us outsiders/readers, it's always difficult to tell whether something is useful/convenient or not as we might not have the need for it yet but I guess OP might have already be using similar code multiple times so in his projects this is a convenience. Another such example could be my extensions for testing common interfaces. Not much feedback received, probalby because nobody is doing this but I'm using them in many projects; it's relative :-]
                        – t3chb0t
                        May 3 at 10:49













                        CountEqual and CountNotEqual don't quite work, at least the way it's posted here, you should run the tests OP has provided.
                        – Denis
                        May 3 at 10:51




                        CountEqual and CountNotEqual don't quite work, at least the way it's posted here, you should run the tests OP has provided.
                        – Denis
                        May 3 at 10:51












                        @Flater those 2 tests specifically Console.WriteLine("F? " + things.CountEqual(x => x <= 5, 2));, Console.WriteLine("T? " + things.CountNotEqual(x => x <= 5, 2));.
                        – Denis
                        May 3 at 11:00





                        @Flater those 2 tests specifically Console.WriteLine("F? " + things.CountEqual(x => x <= 5, 2));, Console.WriteLine("T? " + things.CountNotEqual(x => x <= 5, 2));.
                        – Denis
                        May 3 at 11:00











                        up vote
                        4
                        down vote













                        A method that returns a count and stop at a target count can do all that logic.

                        I like more mathematical names.



                        public static class IEnumerableTCountExtensions

                        private static int CountMatchingStopAt<T>(IEnumerable<T> items, Func<T, bool> predicate, int stopAt)

                        int count = 0;
                        foreach (var item in items)

                        if (predicate.Invoke(item))

                        count++;
                        if(count == stopAt)

                        break;



                        return count;

                        public static bool GreaterThanOrEqual<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

                        return CountMatchingStopAt(items, predicate, required + 1) >= required;

                        public static bool GreaterThan<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

                        return CountMatchingStopAt(items, predicate, required + 1) == required + 1;

                        public static bool Equal<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

                        return CountMatchingStopAt(items, predicate, required + 1) == required;

                        public static bool NotEqual<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

                        return CountMatchingStopAt(items, predicate, required + 1) != required;

                        public static bool LessThan<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

                        return CountMatchingStopAt(items, predicate, required) < required;

                        public static bool LessThanOrEqual<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

                        return CountMatchingStopAt(items, predicate, required + 1) <= required;







                        share|improve this answer



























                          up vote
                          4
                          down vote













                          A method that returns a count and stop at a target count can do all that logic.

                          I like more mathematical names.



                          public static class IEnumerableTCountExtensions

                          private static int CountMatchingStopAt<T>(IEnumerable<T> items, Func<T, bool> predicate, int stopAt)

                          int count = 0;
                          foreach (var item in items)

                          if (predicate.Invoke(item))

                          count++;
                          if(count == stopAt)

                          break;



                          return count;

                          public static bool GreaterThanOrEqual<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

                          return CountMatchingStopAt(items, predicate, required + 1) >= required;

                          public static bool GreaterThan<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

                          return CountMatchingStopAt(items, predicate, required + 1) == required + 1;

                          public static bool Equal<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

                          return CountMatchingStopAt(items, predicate, required + 1) == required;

                          public static bool NotEqual<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

                          return CountMatchingStopAt(items, predicate, required + 1) != required;

                          public static bool LessThan<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

                          return CountMatchingStopAt(items, predicate, required) < required;

                          public static bool LessThanOrEqual<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

                          return CountMatchingStopAt(items, predicate, required + 1) <= required;







                          share|improve this answer

























                            up vote
                            4
                            down vote










                            up vote
                            4
                            down vote









                            A method that returns a count and stop at a target count can do all that logic.

                            I like more mathematical names.



                            public static class IEnumerableTCountExtensions

                            private static int CountMatchingStopAt<T>(IEnumerable<T> items, Func<T, bool> predicate, int stopAt)

                            int count = 0;
                            foreach (var item in items)

                            if (predicate.Invoke(item))

                            count++;
                            if(count == stopAt)

                            break;



                            return count;

                            public static bool GreaterThanOrEqual<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

                            return CountMatchingStopAt(items, predicate, required + 1) >= required;

                            public static bool GreaterThan<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

                            return CountMatchingStopAt(items, predicate, required + 1) == required + 1;

                            public static bool Equal<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

                            return CountMatchingStopAt(items, predicate, required + 1) == required;

                            public static bool NotEqual<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

                            return CountMatchingStopAt(items, predicate, required + 1) != required;

                            public static bool LessThan<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

                            return CountMatchingStopAt(items, predicate, required) < required;

                            public static bool LessThanOrEqual<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

                            return CountMatchingStopAt(items, predicate, required + 1) <= required;







                            share|improve this answer















                            A method that returns a count and stop at a target count can do all that logic.

                            I like more mathematical names.



                            public static class IEnumerableTCountExtensions

                            private static int CountMatchingStopAt<T>(IEnumerable<T> items, Func<T, bool> predicate, int stopAt)

                            int count = 0;
                            foreach (var item in items)

                            if (predicate.Invoke(item))

                            count++;
                            if(count == stopAt)

                            break;



                            return count;

                            public static bool GreaterThanOrEqual<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

                            return CountMatchingStopAt(items, predicate, required + 1) >= required;

                            public static bool GreaterThan<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

                            return CountMatchingStopAt(items, predicate, required + 1) == required + 1;

                            public static bool Equal<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

                            return CountMatchingStopAt(items, predicate, required + 1) == required;

                            public static bool NotEqual<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

                            return CountMatchingStopAt(items, predicate, required + 1) != required;

                            public static bool LessThan<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

                            return CountMatchingStopAt(items, predicate, required) < required;

                            public static bool LessThanOrEqual<T>(this IEnumerable<T> items, Func<T, bool> predicate, int required)

                            return CountMatchingStopAt(items, predicate, required + 1) <= required;








                            share|improve this answer















                            share|improve this answer



                            share|improve this answer








                            edited May 3 at 10:49


























                            answered May 3 at 10:12









                            paparazzo

                            4,8131730




                            4,8131730




















                                up vote
                                3
                                down vote














                                Each of them short-circuits as reasonable, to allow us to only enumerate what we have to. The short-circuit path is taken in the case that it's acceptable.




                                Not quite. There are some missing corner cases when required <= 0 (or required < 0 for the exact test).






                                share|improve this answer

























                                  up vote
                                  3
                                  down vote














                                  Each of them short-circuits as reasonable, to allow us to only enumerate what we have to. The short-circuit path is taken in the case that it's acceptable.




                                  Not quite. There are some missing corner cases when required <= 0 (or required < 0 for the exact test).






                                  share|improve this answer























                                    up vote
                                    3
                                    down vote










                                    up vote
                                    3
                                    down vote










                                    Each of them short-circuits as reasonable, to allow us to only enumerate what we have to. The short-circuit path is taken in the case that it's acceptable.




                                    Not quite. There are some missing corner cases when required <= 0 (or required < 0 for the exact test).






                                    share|improve this answer














                                    Each of them short-circuits as reasonable, to allow us to only enumerate what we have to. The short-circuit path is taken in the case that it's acceptable.




                                    Not quite. There are some missing corner cases when required <= 0 (or required < 0 for the exact test).







                                    share|improve this answer













                                    share|improve this answer



                                    share|improve this answer











                                    answered May 3 at 11:59









                                    Peter Taylor

                                    14k2454




                                    14k2454






















                                         

                                        draft saved


                                        draft discarded


























                                         


                                        draft saved


                                        draft discarded














                                        StackExchange.ready(
                                        function ()
                                        StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f193499%2fcounting-elements-meeting-a-predicate-in-an-enumerable-without-iterating-the-ent%23new-answer', 'question_page');

                                        );

                                        Post as a guest













































































                                        Popular posts from this blog

                                        Python Lists

                                        Aion

                                        JavaScript Array Iteration Methods