Question: given IEnumerable<>
, how to check what sequence contains more than x
items?
MCVE:
static void Main(string[] args)
{
var test = Test().Where(o => o > 2 && o < 6); // ToList()
if (test.Count() > 1) // how to optimize this?
foreach (var t in test) // consumer
Console.WriteLine(t);
}
static IEnumerable<int> Test()
{
for (int i = 0; i < 10; i++)
yield return i;
}
The problem here is what Count()
will run complete sequence and that's 1E6
+ items (ToList()
is also bad idea). I am also not allowed to change consumer code (it's a method accepting complete sequence).
In case of large test
collection (when Count()
is expensive) you can try a typical trick:
if (test.Skip(1).Any())
In general case test.Count() > x
can be rewritten into
if (test.Skip(x).Any())
Edit: you may want to hide such a tricks in a method, say EnsureCount
:
public static partial class EnumerableExtensions {
public static IEnumerable<T> EnsureCount<T>(this IEnumerable<T> source, int count) {
if (null == source)
throw new ArgumentNullException("source");
if (count <= 0)
foreach (var item in source)
yield return item;
else {
List<T> buffer = new List<T>(count);
foreach (var item in source) {
if (buffer == null)
yield return item;
else {
buffer.Add(item);
if (buffer.Count >= count) {
foreach (var x in buffer)
yield return x;
buffer = null;
}
}
}
}
}
}
and so your code will be
var test = Test()
.Where(o => o > 2 && o < 6)
.EnsureCount(2); // <- Count() > 1, so at least 2 items
foreach (var t in test)
Console.WriteLine(t);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With