Reputation: 146930
I've got an IEnumerable of T. I wish to skip a certain number of T, but in the process, I also wish to read these T. You can read the Ts with Take() and skip them with Skip(), but that would entail multiple enumerations.
I need to read N items, deal with them, and then get all the unread items back as an IEnumerable, in one enumeration.
Edit: I'm trying to feed an IEnumerable to a method that takes a Stream-alike. Namely, I must implement only the method
public int Read(T[] readBuffer, int offset, int count)
The problem is that I need to advance the enumerable past the read data to store the position and also read the data to pass back out in the input buffer.
So far I've tried this:
public static IEnumerable<T> SkipTake<T>(this IEnumerable<T> input, int num, Action<List<T>> take)
{
var enumerator = input.GetEnumerator();
var chunk = new List<T>();
for (int i = 0; i < num; ++num)
{
chunk.Add(enumerator.Current);
if (!enumerator.MoveNext())
break;
}
take(chunk);
yield return enumerator.Current;
while (enumerator.MoveNext())
yield return enumerator.Current;
}
Not much luck.
Upvotes: 1
Views: 99
Reputation: 7773
Seems like your implementation does not call MoveNext()
at the right time. You must call MoveNext()
before you can get the Current
element:
public static IEnumerable<T> SkipTake<T>(this IEnumerable<T> input, int num, Action<List<T>> take)
{
var enumerator = input.GetEnumerator();
var chunk = new List<T>();
for (int i = 0; i < num; ++num)
{
if (!enumerator.MoveNext())
break;
chunk.Add(enumerator.Current);
}
take(chunk);
while (enumerator.MoveNext())
yield return enumerator.Current;
}
EDIT: Just to make it clear, here's a usage example:
var list = new List<string>() {"This", "is", "an", "example", "!"};
var res = list.SkipTake(2, chunk =>
{
Console.WriteLine(chunk.Count());
});
Console.WriteLine(res.Count());
The output is
2 3
and the collections contain
{"This", "is"}
and
{"an", "example", "!"}
respectively and the original collection list
was not modified.
Upvotes: 1