简体   繁体   中英

Repeatedly Iterating Through a List

I have a list like such:

List<Thing> foo = new List<Thing>();
foo.PopulateWithFourThings();

And I want to iterate through it over and over, such as 0123012301230123...

Foreach is not what I am looking for, because I do not want everything all at once. I have been messing with Queues, and am wondering if Queues are appropriate here? Or if there is something better than Queues for this.

I am looking for the best code practice in this situation (repeatedly iterate through a list).

So is there a better option than:

    if (nextElementIsNeeded)
    {
        Thing thing = foo[0];
        foo.RemoveAt(0);
        foo.Add(thing);
        return thing;
    }

Or the following code using a Queue:

    Queue<Thing> foo = new Queue<Thing>();
    foo.PopulateWithForThings();
    //////////////////////////////////////
    if (nextElementIsNeeded)
    {
        Thing thing = foo.Dequeue();
        foo.Enqueue(thing);
        return thing;
    }

Instead of constantly adding and removing the same Items to/from a collection (no matter which type), simply use a circular index to access the list you have.

int currentElementIndex = 0;
//..

if (nextElementIsNeeded)
{ 
  currentElementIndex = (currentElementIndex + 1) % foo.Count;
  thing = foo[currentElementIndex]; 
} 

Not sure of the practicality, but here's an extension method that would do it:

public static IEnumerable<T> SelectForever<T>(this IEnumerable<T> source)
{
    while(true)
        foreach(T item in source)
            yield return item;
}

or to add a projection:

public static IEnumerable<TResult> SelectForever<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult> selector)
{
    while(true)
        foreach(TSource item in source)
            yield return selector(item);
}

usage would be:

foreach(Thing item in foo.SelectForever())
{
    ...hopefully break at some point
}

or

foreach(string s in foo.SelectForever(item => item.ToString()))
{
    ...hopefully break at some point
}

Note that this is only possible because of deferred execution - calling foo.SelectForever().ToList() would run until it ran out of memory.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM