Y a-t-il un équivalent au f # seq.windowed en C #?
Question
Je travaille sur un code C # traitant de problèmes tels que les moyennes de déménagement, où je dois souvent prendre une liste / ienumerable et travailler sur des morceaux de données consécutives. Le module F # SEQ a une grande fonction, fendue, qui prenant une séquence, renvoie une séquence de morceaux d'éléments consécutifs.
C # a-t-il une fonction équivalente prêt à l'emploi avec LINQ?
La solution
Vous pouvez toujours appeler SeqModule.Windowed
De C #, il vous suffit de référencer FSharp.Core.Dll
. Les noms de fonction sont également légèrement mutilés, alors vous appelez Windowed
plutôt que windowed
, de sorte qu'il correspond aux conventions de capitalisation C #
Autres conseils
Vous pouvez toujours rouler le vôtre (ou traduire celui de F # Core):
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) }
Ma tentative ressemble à ceci, c'est beaucoup plus lent que d'appeler F # directement (comme suggéré par John Palmer). Je suppose que c'est à cause de F # en utilisant un tableau incontrôlé.:
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;
}
La Extensions réactives avoir quelques opérateurs pour vous aider, comme Amortir et Fenêtre. Les extensions interactives, qui peuvent être trouvées dans la branche expérimentale, les ajoutent et un nombre significatif d'opérateurs supplémentaires à LINQ.
John PalmerLa réponse est géniale, voici un exemple basé sur sa réponse.
var numbers = new[] {1, 2, 3, 4, 5};
var windowed = SeqModule.Windowed(2, numbers);
Vous pouvez (ou non) vouloir ajouter à ToArray () à la fin, sans que le type de retour est toujours dans le monde F # (séquence). Avec TOARRAY, il est de retour à C # World (Array).