2012-01-16 26 views
6

Bazı C# kodları üzerinde çalışıyorum, çünkü genellikle bir Liste/IEnumerable almam ve birbirini izleyen verilerden oluşan parçalar üzerinde çalışmam gereken hareketli ortalamalar gibi sorunlarla uğraşıyorum. F # Seq modülü, bir Sıra alarak, ardışık elemanların bir dizi sırasını döndüren, pencereli, harika bir işleve sahiptir.C# içinde F # Seq.windowed için bir eşdeğer var mı?

C#, LINQ ile eşdeğer bir işlev var mı?

+0

Kabul edilen yanıtı veren kullanıcı yanlış olduğunu kabul etti, şimdi başka bir tane seçmeyi düşünebilirsiniz. – Kev

cevap

5

Sadece C# SeqModule.Windowed numaralı telefonu arayarak, sadece FSharp.Core.Dll referansını vermeniz yeterlidir. fonksiyon adları da biraz parçalanmış, bu yüzden C# harf sözleşmeler ile sığacak şekilde size Hep kendi rulo (veya F # çekirdekten birini çevirmek) olabilir

+0

Burada, her zaman bunu yapıyor! Seq.singleton, FSharpSet, adını sen koy. C# kodlamak zorunda kaldığımda, genellikle F # stdlib'yi kullanmaya gelirim. Onsuz nasıl yaşayabilirim? – kkm

+1

Aslında 'SeqModule.Windowed'. –

2

, windowed yerine Windowed çağrı:

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) } 

Denemem böyle görünüyor, sadece F # 'yi (John Palmer tarafından önerildiği gibi) aramaktan daha yavaş. Ben denetlenmeyen dizi .:

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

Aramayı 'arrayInit' ile değiştirin 'var arrR = new T [windowSize]; (int j = 0; j Daniel

+1

"Seq.windowed", "zeroCreateUnchecked" işlevini kullanır, ancak "size" parametresinin geçerliliğini atlar (örn. <0 sonra ise errorArg ... '). Sınır kontrolünden kaçınmıyor. Bu, JITer'in takdirine göre yapılır, inanıyorum. – Daniel

+0

@Daniel, birinin yemini aldığını görmek güzel :) Ama sonuçlarınızı alamıyorum. Varsa, var list = Enumerable.Range (0, 100000); var sw = Stopwatch.StartNew(); int count = list.Windowed (15) .Count(); sw.Stop(); 've sonra Microsoft.FSharp.Collections.SeqModule.Windowed' ile aynı şey (yeni bir aralıkta), C# her zaman kabaca iki kat uzun sürer ... – Benjol

1

Reactive Extensions böyle Buffer ve Window olarak bu konuda yardımcı olacak birkaç operatörleri, sahip kullanarak çünkü F # öyle tahmin ediyorum. Deneysel branşta bulunabilen Etkileşimli Uzantılar, bunları ve önemli sayıda ek operatörü LINQ'a ekler.

İlgili konular