8000 Add sliding window operators with left & right alignment · Issue #153 · morelinq/MoreLINQ · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content
Add sliding window operators with left & right alignment #153
Closed
@atifaziz

Description

@atifaziz

Consider adding sliding window operators (like Windowed already) with left & right alignment. Sliding windows are typically used for statistics like calculating moving averages.

When left-aligned, a window of size N slides over the current and following N-1 elements.

When right-aligned, a window of size N slides over the current and preceding N-1 elements.

In both cases, partial windows should be returned when fewer than N elements (when N > 1) precede (right-aligned) or follow (left-aligned).

Here's a possible implementation:

static partial class MoreEnumerable
{
    public static IEnumerable<IEnumerable<TSource>> WindowRight<TSource>(this IEnumerable<TSource> source, int size)
    {
        return source.WindowRight(size, (_, w) => w);
    }

    public static IEnumerable<TResult> WindowRight<TSource, TResult>(this IEnumerable<TSource> source, int size, Func<TSource, IEnumerable<TSource>, TResult> resultSelector)
    {
        if (source == null) throw new ArgumentNullException("source");
        if (size <= 0) throw new ArgumentOutOfRangeException("size");

        return WindowRightImpl(source, size, resultSelector);
    }

    static IEnumerable<TResult> WindowRightImpl<TSource, TResult>(IEnumerable<TSource> source, int size, Func<TSource, IEnumerable<TSource>, TResult> resultSelector)
    {
        var window = new List<TSource>();
        foreach (var item in source)
        {
            window.Add(item);
            yield return resultSelector(item, window);
            window = new List<TSource>(window.Count == size ? window.Skip(1) : window);
        }
    }

    public static IEnumerable<IEnumerable<TSource>> WindowLeft<TSource>(this IEnumerable<TSource> source, int size)
    {
        return source.WindowLeft(size, (_, w) => w);
    }

    public static IEnumerable<TResult> WindowLeft<TSource, TResult>(this IEnumerable<TSource> source, int size, Func<TSource, IEnumerable<TSource>, TResult> resultSelector)
    {
        if (source == null) throw new ArgumentNullException("source");
        if (size <= 0) throw new ArgumentOutOfRangeException("size");

        return WindowLeftImpl(source, size, resultSelector);
    }

    static IEnumerable<TResult> WindowLeftImpl<TSource, TResult>(IEnumerable<TSource> source, int size, Func<TSource, IEnumerable<TSource>, TResult> resultSelector)
    {
        var window = new List<TSource>();
        foreach (var item in source)
        {
            window.Add(item);
            if (window.Count < size)
                continue;
            yield return resultSelector(window[0], window);
            window = new List<TSource>(window.Skip(1));
        }
        while (window.Count > 0)
        {
            yield return resultSelector(window[0], window);
            window = new List<TSource>(window.Skip(1));
        }
    }
}

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions

    0