sassafrass - 7 months ago 52

C# Question

Say you've got some IEnumerable called S of length N. I would like to select all continuous subsequences of length n <= N from S.

If S were, say, a string, this'd be pretty easy. There are (S.Length - n + 1) subsequences of length n. For example, "abcdefg" is length (7), so that means it has (5) substrings of length (3): "abc", "bcd", "cde", "def", "efg".

But S could be any IEnumerable, so this route isn't open. How do I use extension methods to solve this?

Answer

F# has a library function called Seq.windowed for this.

```
// windowed : int -> seq<'a> -> seq<array<'a>>
let windowed n (s: seq<_>) =
if n <= 0 then Helpers.invalid_arg2 "n" "the window size must be positive"
{ let arr = Array.zero_create n
let r = ref (n-1)
let i = ref 0
use e = s.GetEnumerator()
while e.MoveNext() do
do arr.[!i] <- e.Current
do i := (!i + 1) % n
if !r = 0 then
yield Array.init n (fun j -> arr.[(!i+j) % n])
else
do r := (!r - 1) }
```