J'essaie d'apprendre F # en réécrivant certains algorithmes C # je suis dans idiomatique F #.
L'une des premières fonctions que j'essaie de réécrire est un lots de latche où: p> qui diviserait la séquence en lots avec un max de cinq dans chacun, c'est-à-dire : p> Ma première tentative de faire est une sorte de moche où j'ai eu recours à un objet mutable ref fort> ref fort> Utilisez let batchesOf size (sequence: _ seq) : _ list seq =
seq {
let s = ref sequence
while not (!s |> Seq.isEmpty) do
yield !s |> Seq.truncate size |> List.ofSeq
s := System.Linq.Enumerable.Skip(!s, size)
}
10 Réponses :
Mise en œuvre de cette fonction à l'aide du type si vous ' Reprendre F #, il est préférable d'essayer d'écrire la fonction à l'aide du type de liste F #. De cette façon, vous pouvez utiliser un style fonctionnel idiomatique. Ensuite, vous pouvez écrire comme note de bas de page, la version impérative peut être apportée un peu Noir en utilisant Expression de calcul em> pour travailler avec SEQ <_> CODE> Idiomatiquement est difficile - le type est intrinsèquement mutable, donc il n'y a pas de simple façon fonctionnelle. Votre version est assez inefficace, car elle utilise
Ignorer code> à plusieurs reprises sur la séquence. Un meilleur l'option impérative em> serait d'utiliser
getenumerator code> et simplement itérer sur des éléments utilisant
ienumerator code>. Vous pouvez trouver diverses options impératives de cet extrait: http://fssnip.net/1o
lotsof code> à l'aide de la correspondance de motif avec la récursion et l'argument de l'accumulateur, comme celui-ci: p>
ienumerator code>, mais ce n'est pas standard et que c'est un tour assez avancé (par exemple, voir http://fssnip.net/37 ). P> p>
Doux remerciements pour les explications détaillées et des liens vers les alternatives!
Ceci peut être fait sans récursion si vous voulez
[0..20] |> Seq.mapi (fun i elem -> (i/size),elem) |> Seq.groupBy (fun (a,_) -> a) |> Seq.map (fun (_,se) -> se |> Seq.map (snd));; val it : seq<seq<int>> = seq [seq [0; 1; 2; 3; ...]; seq [5; 6; 7; 8; ...]; seq [10; 11; 12; 13; ...]; seq [15; 16; 17; 18; ...]; ...]
En utilisant GroupBy CODE> est une jolie truc soie - je pense que c'est une excellente approche pour une implémentation initiale de prototype (que vous pouvez être faite rapidement et facilement). Je suppose que la performance sera un peu un problème cependant. La version récursive sera probablement un peu meilleure et les solutions impératives de l'extrait que je parlent plus rapidement. Mais la performance n'est souvent pas un problème lors du prototypage et des tests.
Notez que groupby code> ne fournit probablement aucune assurance qu'elle préserve l'ordre des éléments. J'ai été très surpris quand j'ai découvert que
PSEQ code> fonctionne de manière non déterministe vos séquences ...
Ce n'est peut-être pas idiomatique, mais cela fonctionne:
let batchesOf n l = let _, _, temp', res' = List.fold (fun (i, n, temp, res) hd -> if i < n then (i + 1, n, hd :: temp, res) else (1, i, [hd], (List.rev temp) :: res)) (0, n, [], []) l (List.rev temp') :: res' |> List.rev
Sont les citations simples sur Temp 'et Res' une convention F #?
Non, je ne pense pas dans ce cas. Je n'ai tout simplement pas eu l'imagination de faire venir avec plus de noms descriptifs :-)
Voici une implémentation simple pour les séquences:
Un ami m'a demandé cela un peu de retour. Voici une réponse recyclée. Cela fonctionne et est pur: ou une version impure: p> Ceux-ci produisent un espère que cela aide! p> p> SEQ
'une liste de liste code> comme dans votre exemple, ajoutez simplement
... |> seq.map (list.ofseq) |> list.oFseq code> dans: p>
+1 Pour écrire le code le plus élégant dans l'exemple supérieur. J'utiliserais cela par défaut, sauf indication claire que les lieux du code où il est appliqué est relativement performant, comparé à d'autres lieux de code et la différence de performance est réellement perceptible par l'utilisateur.
Oui, c'est pur, mais ce n'est pas paresseux. L'appel Groupby consomme avec impatience l'ensemble de la séquence d'intrants, qui conflit dans le but de lotter les articles en premier lieu.
Vous pouvez résoudre votre tâche avec analogique de Clojure < Code> partition code> Fonction de la bibliothèque ci-dessous: utilisé comme partition comme prime en jouant avec considère comme un prototype 5 5 code> Il vous fournira recherché
lots de 5 code> fonctionnalité: p>
N code> et
étape code> Vous pouvez l'utiliser pour la tranchée chevauchement des lots alias
Cette version passe tous mes tests que je pourrais penser, y compris ceux de l'évaluation paresseux et une évaluation de la séquence unique: Je suis toujours assez nouveau à f # donc si je manque quelque chose - s'il vous manque quelque chose corrige-moi, ce sera grandement apprécié. p> p>
Ma méthode consiste à convertir la liste en une matrice et de chunking récursivement le tableau:
let batchesOf (sz:int) lt = let arr = List.toArray lt let rec bite curr = if (curr + sz - 1 ) >= arr.Length then [Array.toList arr.[ curr .. (arr.Length - 1)]] else let curr1 = curr + sz (Array.toList (arr.[curr .. (curr + sz - 1)])) :: (bite curr1) bite 0 batchesOf 5 [1 .. 17] [[1; 2; 3; 4; 5]; [6; 7; 8; 9; 10]; [11; 12; 13; 14; 15]; [16; 17]]
J'ai trouvé que ceci comme une solution assez terres: Il fonctionne sur une séquence et produit une séquence. La séquence de sortie consiste en des listes de n éléments de la séquence d'entrée. P> p>
hurray, nous pouvons utiliser list.chunkbysize code>,
seq.chunkbysize code> et
array.chunkbysize code> dans F # 4, comme mentionné par Brad Collins et Scott Wlaschin . P>
Related: Stackoverflow.com/questions/7044100/... Stackoverflow.com/Questtions/6736464/split-seq-in-f/... a >
Vaguement lié à
Voir également l'opération "Chunking" en Deedle: bluemountaintacital.github.io/deedle/timesseries.html#windowi ng (via @tomas Petricek)