Reputation: 35631
Given a finite list of elements, how can I create a (lazily-evaluated, thanks LINQ!) infinite list that just keeps iterating over my initial list?
If the initial list is {1, 2, 3}
, I want the new list to return {1, 2, 3, 1, 2, 3, 1, ...}
Upvotes: 10
Views: 2604
Reputation: 14851
yield return
is a fairly handy operator for this, although it doesn't really require LINQ specifically.
IEnumerable<int> GetInfiniteSeries(IEnumerable<int> items) {
while (true) {
foreach (var item in items) {
yield return item;
}
}
}
Upvotes: 19
Reputation: 62027
Another option, implement IEnumerator<T>
:
public class InfiniteEnumerator<T> : IEnumerator<T>
{
private IList<T> _items;
private int _index = -1;
public InfiniteEnumerator(IList<T> items)
{
if (items == null)
{
throw new ArgumentNullException("items");
}
_items = items;
}
public T Current
{
get { return _items[_index]; }
}
public void Dispose()
{
}
object System.Collections.IEnumerator.Current
{
get { return _items[_index]; }
}
public bool MoveNext()
{
if (_items.Count == 0)
{
return false;
}
_index = (_index + 1) % _items.Count;
return true;
}
public void Reset()
{
_index = -1;
}
}
Upvotes: 3
Reputation: 35631
Here's how I've done it eventually:
public static IEnumerable<T> AdNauseam<T>(this IEnumerable<T> i_list)
{
using(var etor = i_list.GetEnumerator())
{
while(true)
{
while(etor.MoveNext())
{
yield return etor.Current;
}
etor.Reset();
}
}
}
Usage:
var list = new[] {1, 2, 3}
var infinite = list.AdNauseam().Take(10);
The result:
{1, 2, 3, 1, 2, 3, 1, 2, 3, 1}
Upvotes: 3
Reputation: 103495
IEnumerable<T> Infinite(this IEnumerable<T> ienum)
{
List<T> list = ienum.ToList();
while (true)
foreach(var t in list)
yield return t;
}
foreach(int i in Enumerable.Range(1,3).Infinite())
Console.WriteLine(i);
Upvotes: 6