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?

Était-ce utile?

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

enter image description here

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top