I need to iterate over a list while getting the next and previous Items. I'm currently doing it like so:
var items = collection.ToList();
for (int index = 0; index < items.Count; index++)
{
var prevItem = index == 0 ? null : items[index - 1];
var currentItem = items[index];
var nextItem = (index + 1) == items.Count ? null : items[index + 1];
// do work
}
This work but it is not as nice and readable as I would like. Is there a more readable way of creating a sliding window? which doesn't involve all of the ugly ternary checks. I feel like there is a more friendly way using select, skip, take, and default if empty
This sort of problem is best solved using generators if you want it to be reusable IMHO.
public static IEnumerable<(T PrevItem, T CurrentItem, T NextItem)>
SlidingWindow<T>(this IEnumerable<T> source, T emptyValue = default)
{
using (var iter = source.GetEnumerator())
{
if (!iter.MoveNext())
yield break;
var prevItem = emptyValue;
var currentItem = iter.Current;
while (iter.MoveNext())
{
var nextItem = iter.Current;
yield return (prevItem, currentItem, nextItem);
prevItem = currentItem;
currentItem = nextItem;
}
yield return (prevItem, currentItem, emptyValue);
}
}
Then use it:
foreach (var (prevItem, currentItem, nextItem) in collection.SlidingWindow())
{
// do stuff with prevItem, currentItem, nextItem
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With