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.Value < chunkSize && e.MoveNext() do buffer.[i.Value] <- e.Current i.Value <- i.Value + 1 let copyAndSlideBack() = let res = Array.copy buffer System.Array.Copy(res,stride,buffer,0,chunkSize-stride) res while go.Value do fillBuffer() let res = copyAndSlideBack() go.Value <- i.Value = chunkSize if go.Value then i.Value <- chunkSize-stride yield res else let m = res.[0..i.Value-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|]|] *)