我正在處理一些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