我正在处理一些C#代码,这些代码处理移动平均数等问题,我经常需要使用List/IEnumerable并处理连续数据块。 F#Seq模块有一个很好的功能,窗口化,它接受一个序列,返回一系列连续元素的序列。是否有与C#中的F#Seq.windowed相当的功能?
C#是否具有LINQ的开箱即用功能?
我正在处理一些C#代码,这些代码处理移动平均数等问题,我经常需要使用List/IEnumerable并处理连续数据块。 F#Seq模块有一个很好的功能,窗口化,它接受一个序列,返回一系列连续元素的序列。是否有与C#中的F#Seq.windowed相当的功能?
C#是否具有LINQ的开箱即用功能?
你可以随时从C#调用SeqModule.Windowed
,你只需要参考FSharp.Core.Dll
。该功能的名称也略有错位,所以你打电话Windowed
而非windowed
,使其与C#的大小写约定适合
在这里,在这里,一直这样做! Seq.singleton,FSharpSet,你的名字。当我必须用C#编写代码时,我经常使用F#stdlib。没有它我怎么能活下去! – kkm 2012-01-16 04:45:20
实际上它是'SeqModule.Windowed'。 – 2012-01-16 13:30:03
你总是可以推出自己的(或翻译从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#要慢(正如John Palmer所建议的)。我使用的是未经检查的数组:
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;
}
用'var arrR = new T [windowSize];将调用替换为'ArrayInit'; for(int j = 0; j
'Seq.windowed'使用'zeroCreateUnchecked',但它只是跳过'size'参数的验证(即如果size <0 then invalidArg ...')。它不避免边界检查。我相信这是由JITer自行决定的。 – Daniel 2012-01-16 15:44:43
@丹尼尔,很高兴看到有人拿着诱饵:)我不能得到你的结果。如果我做'var list = Enumerable.Range(0,100000); var sw = Stopwatch.StartNew(); int count = list.Windowed(15).Count(); sw.Stop();'然后'Microsoft.FSharp.Collections.SeqModule.Windowed'(在一个新的范围),同样的事情,C#总是需要大约两倍长... – Benjol 2012-01-17 05:46:29
的Reactive Extensions有几个运营商来解决这个问题,比如Buffer和Window猜测这是因为F#。可以在实验分支中找到交互式扩展,将这些和大量额外的运算符添加到LINQ中。
提供已接受答案的用户承认这是错误的,您现在可能需要考虑选择另一个答案。 – Kev 2012-01-17 00:01:16