Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create a sliding window from a list

Tags:

c#

linq

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

like image 868
johnny 5 Avatar asked Nov 15 '25 07:11

johnny 5


1 Answers

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
}
like image 145
Jeff Mercado Avatar answered Nov 17 '25 20:11

Jeff Mercado