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 th开发者_Go百科e new list to return {1, 2, 3, 1, 2, 3, 1, ...}
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;
}
}
}
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);
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}
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;
}
}
精彩评论