patterncsharpModerate
Cycle through an IEnumerable
Viewed 0 times
cycleienumerablethrough
Problem
I built an extension method to cycle through all items of an
So when you do
The result is 6,7,8,9,10,1,2,3,4,5.
What I don't like is the use of the
EDIT:
I use an enumerator to iterate the enumerable not more than once.
IEnumerable starting at some index: public static IEnumerable Circle(this IEnumerable list, int startIndex)
{
if (list != null)
{
List firstList = new List();
using (var enumerator = list.GetEnumerator())
{
int i = 0;
while (enumerator.MoveNext())
{
if (i < startIndex)
{
firstList.Add(enumerator.Current);
i++;
}
else
{
yield return enumerator.Current;
}
}
}
foreach (var first in firstList)
{
yield return first;
}
}
yield break;
}So when you do
Enumerable.Range(1,10).Circle(5);The result is 6,7,8,9,10,1,2,3,4,5.
What I don't like is the use of the
firstList variable. Is there a way to do this with the enumerator only, without storing an intermediate result?EDIT:
I use an enumerator to iterate the enumerable not more than once.
Solution
A shorter form of Trevor's answer (but essentially doing the same thing):
This will still lazy evaluate just like Trevor's answer, because
Further more, if you have written a method to cycle through an
Lastly, I'd actually recommend taking advantage of lazy evaluation to give you a more useful method. The one below will continue to cycle indefinitely, starting with an optional index:
Then you can do something like:
And this lets you specify just how many repeated items you want.
public static IEnumerable Circle(this IEnumerable list, int startIndex)
{
return list.Skip(startIndex).Concat(list.Take(startIndex));
}This will still lazy evaluate just like Trevor's answer, because
Concat lazily evaluates.Further more, if you have written a method to cycle through an
IEnumerable, why not call it Cycle?Lastly, I'd actually recommend taking advantage of lazy evaluation to give you a more useful method. The one below will continue to cycle indefinitely, starting with an optional index:
public static IEnumerable Cycle(this IEnumerable list, int index = 0)
{
var count = list.Count();
index = index % count;
while(true)
{
yield return list.ElementAt(index);
index = (index + 1) % count;
}
}Then you can do something like:
foreach(var num in Enumerable.Range(1, 10).Cycle(4).Take(30))
{
Console.WriteLine(num.ToString());
}And this lets you specify just how many repeated items you want.
Code Snippets
public static IEnumerable<T> Circle<T>(this IEnumerable<T> list, int startIndex)
{
return list.Skip(startIndex).Concat(list.Take(startIndex));
}public static IEnumerable<T> Cycle<T>(this IEnumerable<T> list, int index = 0)
{
var count = list.Count();
index = index % count;
while(true)
{
yield return list.ElementAt(index);
index = (index + 1) % count;
}
}foreach(var num in Enumerable.Range(1, 10).Cycle(4).Take(30))
{
Console.WriteLine(num.ToString());
}Context
StackExchange Code Review Q#9088, answer score: 10
Revisions (0)
No revisions yet.