c# MoreLinq 之 Window

2021-02-21  本文已影响0人  wwmin_

前言

本系列是对MoreLinq库的学习与总结,分析各个Api的实现方式及用法,也为能写出更高效的Linq打下基础。

window 依据个数依次返回指定大小窗口数据

//window 一次选取若干个相同数量且连续的数据, 
//如同使用带有窗口的卡尺一次移动一个位置看到的连续数据的效果
void WindowFunc()
{
    var a = new List<int> { 1, 2, 3, 4, 5 };
    foreach (var t in a.Window(4))
    {
        var s = string.Join(',', t);
        s.Dump();
    }
}

结果是:

1,2,3,4
2,3,4,5

Window定义:

public static class MoreEnumerable
{
        /// <summary>
        /// Processes a sequence into a series of subsequences representing a windowed subset of the original
        /// </summary>
        /// <remarks>
        /// The number of sequences returned is: <c>Max(0, sequence.Count() - windowSize) + 1</c><br/>
        /// Returned subsequences are buffered, but the overall operation is streamed.<br/>
        /// </remarks>
        /// <typeparam name="TSource">The type of the elements of the source sequence</typeparam>
        /// <param name="source">The sequence to evaluate a sliding window over</param>
        /// <param name="size">The size (number of elements) in each window</param>
        /// <returns>A series of sequences representing each sliding window subsequence</returns>
    public static IEnumerable<IList<TSource>> Window<TSource>(this IEnumerable<TSource> source, int size)
    {
        if (source == null) throw new ArgumentNullException(nameof(source));
        if (size <= 0) throw new ArgumentOutOfRangeException(nameof(size));
        return _();
        IEnumerable<IList<TSource>> _()
        {
            using var iter = source.GetEnumerator();
            var window = new TSource[size];
            int i;
            for (i = 0; i < size && iter.MoveNext(); i++)
            {
                window[i] = iter.Current;
            }
            if (i < size)
                yield break;

            while (iter.MoveNext())
            {
                var newWindow = new TSource[size];
                Array.Copy(window, 1, newWindow, 0, size - 1);
                newWindow[size - 1] = iter.Current;

                yield return window;
                window = newWindow;
            }
            yield return window;

        }
    }
}

分析:
首先遍历指定大小的数据形成第一条window,此时没有返回数据直接遍历下一条window,形成之后便返回第一条window,继续遍历则重复上一个操作的流程,直到数据结尾。
在形成window时使用了Array.Copy(oldArray,oldArrayStartIndex,newArray,newArrayStartIndex,newArrayEndIndex)方法。
并且整个实现使用了yield返回迭代对象的方法。

本文作者:wwmin
微信公众号: DotNet技术说
本文链接:https://www.jianshu.com/p/71ae431921b8
关于博主:评论和私信会在第一时间回复。或者[直接私信]我。
版权声明:转载请注明出处!
声援博主:如果您觉得文章对您有帮助,关注点赞, 您的鼓励是博主的最大动力!

上一篇下一篇

猜你喜欢

热点阅读