A real LINQ solution is possible, but frankly pretty ugly. The idea is to isolate subsequences that match the description (a series of N elements matching the predicate that ends when the element is found matching the second predicate), and then select the first one with the shortest length.
Let's say the parameters are:
var data = new[] { 0, 1, 1, 1, 0, 0, 2, 2, 2, 2, 2 }; Func<int, bool> acceptPredicate = i => i != 0;
Isolating subsequences are possible with GroupBy and a bunch of ugly GroupBy code (there is an inherent awkwardness here - you need to maintain a non-trivial state). The idea is to group with an artificial and arbitrary โgroup numberโ, choosing a different number whenever we move from a subsequence that can be acceptable to one that is definitely unacceptable and when the opposite happens:
var acceptMode = false; var groupCount = 0; var groups = data.GroupBy(i => { if (acceptMode && rejectPredicate(i)) { acceptMode = false; ++groupCount; } else if (!acceptMode && acceptPredicate(i)) { acceptMode = true; ++groupCount; } return groupCount; });
The last step (finding the first group of acceptable length) is simple, but there is one last mistake: make sure that you do not select one of the groups that do not satisfy the specified condition:
var result = groups.Where(g => !rejectPredicate(g.First())) .FirstOrDefault(g => g.Count() >= 5);
All of the above is achieved in one pass along the original sequence.
Please note that this code will take a sequence of elements that also ends the original sequence (i.e. it does not end because we found an element that satisfies rejectPredicate , but because we ran out of data). If you do not want this, a small modification is required.
Look at the action .