module Seq = let stridedChunks stride chunkSize (source : seq<_> ) = if stride <= 0 then failwith "stride should be a positive integer" if chunkSize <= 0 then failwith "chunkSize should be a positive integer" if stride > chunkSize then failwith "stride > chunkSize not supported" seq { use e = source.GetEnumerator() let buffer = Array.zeroCreate chunkSize let go = ref true let i = ref 0 let fillBuffer() = while !i < chunkSize && e.MoveNext() do buffer.[!i] <- e.Current i := !i + 1 let copyAndSlideBack() = let res = Array.copy buffer System.Array.Copy(res,stride,buffer,0,chunkSize-stride) res while !go do fillBuffer() let res = copyAndSlideBack() go := !i = chunkSize if !go then i := chunkSize-stride yield res else let m = res.[0..!i-1] if m.Length > 0 then yield m } (* let t = [0;1;2;3;4;5;6] stridedChunks 2 4 t // val it : seq = seq [[|0; 1; 2; 3|]; [|2; 3; 4; 5|]; [|4; 5; 6|]] stridedChunks 1 3 t |> Seq.toArray // val it : int [] [] = [|[|0; 1; 2|]; [|1; 2; 3|]; [|2; 3; 4|]; [|3; 4; 5|]; [|4; 5; 6|]; [|5; 6|]|] stridedChunks 1 1 t |> Seq.toArray //val it : int [] [] = [|[|0|]; [|1|]; [|2|]; [|3|]; [|4|]; [|5|]; [|6|]|] *)