2012-01-16 28 views
6

私はList/IEnumerableをとり、連続したデータのまとまりを扱う必要がある移動平均のような問題を扱うC#コードを作成しています。 F#Seqモジュールは、シーケンスを取る大きな関数を持っていて、連続した要素のチャンクのシーケンスを返します。F#Seq.windowedと同等のものがC#にありますか?

C#には、LINQと同等の機能がありますか?

+0

受け入れられた回答を提供したユーザーが間違っていたと認めた場合は、別のユーザーを選択することを検討することをおすすめします。 – Kev

答えて

5

いつでもSeqModule.WindowedをC#から呼び出すことができます。ちょうどFSharp.Core.Dllを参照する必要があります。関数名もわずかマングルされているので、それはC#の総額規則に合うように、あなたは常に独自のロール(またはF#のコアから1変換する)ことができ

+0

ここ、ここで、いつもそれをやって! Seq.singleton、FSharpSet、名前を付けます。 C#でコードを作成する必要があるときは、F#stdlibを使用することがよくあります。それがなければ、どうすれば私は生きることができますか – kkm

+1

実際には 'SeqModule.Windowed'です。 –

2

windowedではなくWindowedを呼び出す:

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の示唆)。私はそれが未確認のアレイを使用しているための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; 
} 
+0

'ArrayInit'への呼び出しを' var arrR = new T [windowSize];に置き換えます。 (int j = 0; j Daniel

+1

'Seq.windowed'は' zeroCreateUnchecked'を使いますが、 'size'パラメータ(' size <0 then invalidArg ... ')の検証をスキップするだけです。境界チェックを回避しません。これはJITerの裁量で行なわれたものだと私は信じている。 – Daniel

+0

@ダニエル、誰かが餌を取ってくれてうれしい:)私はあなたの結果を得ることができません。もし私が 'var list = Enumerable.Range(0、100000); var sw = Stopwatch.StartNew(); int count = list.Windowed(15).Count(); (新しい範囲で) 'Microsoft.FSharp.Collections.SeqModule.Windowed'で同じことをすると、C#は常に約2倍の時間がかかります... – Benjol

1

Reactive Extensionsは、BufferWindowとしてこれを支援するためにいくつかの演算子を持っています。実験的なブランチにあるInteractive Extensionsは、これらと多くの追加演算子をLINQに追加します。