如何通过 IEnumerable 访问 foreach 迭代中的下一个和上一个项目?

我想在处理当前项目并迭代 时访问下一个和上一个项目(如果在范围内)IEnumerable<object>,它缺少索引器(据我所知)。


我不想要求一个List<object>集合或一个数组来实现这一点,尽管这是我现在所知道的唯一选择。


如果可能的话,我也更愿意避免使用 Linq 表达式。


目前我的方法就是这样定义的:


public static void PrintTokens(IEnumerable<object> tokens)

{

    foreach (var token in tokens)

    {

        // var next = ?

        // var prev = ?

    }

}


陪伴而非守候
浏览 81回答 5
5回答

德玛西亚99

您像往常一样执行循环,但是您当前所在的项目变为next,前一个项目为current,而之前的项目为prev。object prev = null;object current = null;bool first = true;foreach (var next in tokens){&nbsp; &nbsp; if (!first)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; Console.WriteLine("Processing {0}. Prev = {1}. Next = {2}", current, prev, next);&nbsp; &nbsp; }&nbsp; &nbsp; prev = current;&nbsp; &nbsp; current = next;&nbsp; &nbsp; first = false;}// Process the final item (if there is one)if (!first){&nbsp; &nbsp; Console.WriteLine("Processing {0}. Prev = {1}. Next = {2}", current, prev, null);}如果您使用的是 C# 7.0+,则可以编写(prev, current, first) = (current, next, false);而不是循环末尾的三个单独的语句。

慕盖茨4494581

For循环最好:for (int i = 0; i < tokens.Count(); i++){&nbsp; &nbsp; token prv = i > 0 ? tokens[i-1] : null;&nbsp; &nbsp; token cur = tokens[i];&nbsp; &nbsp; token nxt = i < tokens.Count() ? tokens[i+1] : null;}然后就像你问的那样,你可以很容易地设置循环中的当前、上一个和下一个对象变量来使用。编辑:我想知道为什么这不是一个好的解决方案,因为它是我正在使用的。

慕工程0101907

我写了一个扩展方法,它返回一个包含 3 个对象的元组:上一个、当前和下一个:public static class Extensions{&nbsp; &nbsp; public static IEnumerable<Tuple<T, T, T>> GetItems<T>(this IEnumerable<T> source)&nbsp; &nbsp; &nbsp; &nbsp; where T : class&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; if (source != null)&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // skip the first iteration to be able to include next item&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; bool skip = true;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; T previous = default(T), current = default(T), next = default(T);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; foreach (T item in source)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; next = item;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (!skip)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; yield return new Tuple<T, T, T>(previous, current, next);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; previous = current;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; current = item;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; skip = false;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (!skip)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; next = default(T);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; yield return new Tuple<T, T, T>(previous, current, next);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }}希望能帮助到你。也许使用自定义类而不是元组进行扩展。

繁星点点滴滴

你可以试试这个扩展方法。它是获取“大小”上一个项目和“大小”下一个项目和当前项目:&nbsp; &nbsp; public static System.Collections.Generic.IEnumerable<TResult> Select<TSource, TResult>(this System.Collections.Generic.IEnumerable<TSource> source, int size, System.Func<Queue<TSource>, TSource, Queue<TSource>, TResult> selector)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; if (source == null)&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; throw new System.ArgumentNullException("source");&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; if (selector == null)&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; throw new System.ArgumentNullException("selector");&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; Queue<TSource> prevQueue = new Queue<TSource>(size);&nbsp; &nbsp; &nbsp; &nbsp; Queue<TSource> nextQueue = new Queue<TSource>(size);&nbsp; &nbsp; &nbsp; &nbsp; int i = 0;&nbsp; &nbsp; &nbsp; &nbsp; foreach (TSource item in source)&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nextQueue.Enqueue(item);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (i++ >= size)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; TSource it = nextQueue.Dequeue();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; yield return selector(prevQueue, it, nextQueue);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; prevQueue.Enqueue(it);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (prevQueue.Count > size)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; prevQueue.Dequeue();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; while (nextQueue.Any())&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; TSource it = nextQueue.Dequeue();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; yield return selector(prevQueue, it, nextQueue);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; prevQueue.Enqueue(it);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (prevQueue.Count > size)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; prevQueue.Dequeue();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }

慕运维8079593

除非我遗漏了什么,否则 for 循环不是最简单和最有效的方法吗?for (int i = 0; i < tokens.Count(); i++){&nbsp; &nbsp; token previous = i > 0 ? tokens[i - 1] : null;&nbsp; &nbsp; token current = tokens[i];&nbsp; &nbsp; token next = i < tokens.Count() ? tokens[i + 1] : null;}那么你当前的循环索引就是实际的循环项,previous 和 next 很容易得到,不需要“你当前的循环对象是前一个对象”,也不需要循环外单独的'if'。
打开App,查看更多内容
随时随地看视频慕课网APP