English 中文(简体)
C#中是否有类似于F# Seq.windowed?
原标题:Is there an equivalent to the F# Seq.windowed in C#?

我正在拟订一些C#代码,处理移动平均数等问题,我经常需要编制一个清单/数字,并处理连续数据丘。 F# Seq模块具有很强的功能,窗户是按顺序排列的,接回了连续元素的顺序。

Does C# have an equivalent function out-of-the-box with LINQ?

最佳回答

您总是可以打电话到<条码>。 SeqModule.Windowed from C#, You only need to reference FSharp.Core.Dll. 功能名称也稍有改动,因此,请打电话windowed<>/code>,而不是windowed,以便与C# Capitalisation conventions保持一致。

问题回答

您可以永远发挥自己的作用(或从F#核心中翻译):

let windowed windowSize (source: seq<_>) =    
    checkNonNull "source" source
    if windowSize <= 0 then invalidArg "windowSize" (SR.GetString(SR.inputMustBeNonNegative))
    seq { let arr = Microsoft.FSharp.Primitives.Basics.Array.zeroCreateUnchecked windowSize 
            let r = ref (windowSize-1)
            let i = ref 0 
            use e = source.GetEnumerator() 
            while e.MoveNext() do 
                arr.[!i] <- e.Current
                i := (!i + 1) % windowSize
                if !r = 0 then 
                    yield Array.init windowSize (fun j -> arr.[(!i+j) % windowSize])
                else 
                r := (!r - 1) }

我的尝试就是这样,它比直接叫F#(正如约翰·帕尔默所建议的)要慢得多。 I m 猜测,因为F#使用一个无法核对的阵列。

public static IEnumerable<T[]> Windowed<T>(this IEnumerable<T> list, int windowSize)
{
    //Checks elided
    var arr = new T[windowSize];
    int r = windowSize - 1, i = 0;
    using(var e = list.GetEnumerator())
    {
        while(e.MoveNext())
        {
            arr[i] = e.Current;
            i = (i + 1) % windowSize;
            if(r == 0) 
                yield return ArrayInit<T>(windowSize, j => arr[(i + j) % windowSize]);
            else
                r = r - 1;
        }
    }
}
public static T[] ArrayInit<T>(int size, Func<int, T> func)
{
    var output = new T[size];
    for(var i = 0; i < size; i++) output[i] = func(i);
    return output;
}

John Palmer s answer is great, here is an example based on his answer.

var numbers = new[] {1, 2, 3, 4, 5}; 
var windowed = SeqModule.Windowed(2, numbers);

如果没有ToArray,你可能(或不是)希望最终增加ToArray(),返回类型仍留在F# World(Sequence)。 有了ToArray,它就回到了C# World(Array)。

enter image description here

The Reactive Extensions have a few operators to help with this, such as Buffer and Window. The Interactive Extensions, which can be found in the experimental branch, add these and a significant number of additional operators to LINQ.





相关问题
Anyone feel like passing it forward?

I m the only developer in my company, and am getting along well as an autodidact, but I know I m missing out on the education one gets from working with and having code reviewed by more senior devs. ...

NSArray s, Primitive types and Boxing Oh My!

I m pretty new to the Objective-C world and I have a long history with .net/C# so naturally I m inclined to use my C# wits. Now here s the question: I feel really inclined to create some type of ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

How to Use Ghostscript DLL to convert PDF to PDF/A

How to user GhostScript DLL to convert PDF to PDF/A. I know I kind of have to call the exported function of gsdll32.dll whose name is gsapi_init_with_args, but how do i pass the right arguments? BTW, ...

Linqy no matchy

Maybe it s something I m doing wrong. I m just learning Linq because I m bored. And so far so good. I made a little program and it basically just outputs all matches (foreach) into a label control. ...