Учитывая конечный список элементов, как я могу создать (с ленивой оценкой, спасибо LINQ!) Бесконечный список, который просто продолжает повторяться над моим исходным списком?
Если исходный список {1, 2, 3}
, я хочу, чтобы новый список возвращал {1, 2, 3, 1, 2, 3, 1, ...}
yield return
— довольно удобный оператор для этого, хотя на самом деле он не требует специального LINQ.
IEnumerable<int> GetInfiniteSeries(IEnumerable<int> items) {
while (true) {
foreach (var item in items) {
yield return item;
}
}
}
Вот как я это сделал в итоге:
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();
}
}
}
Использование:
var list = new[] {1, 2, 3}
var infinite = list.AdNauseam().Take(10);
Результат:
{1, 2, 3, 1, 2, 3, 1, 2, 3, 1}
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);
Другой вариант, реализовать IEnumerator
:
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;
}
}