sassafrass sassafrass - 1 year ago 81
C# Question

Select the next N elements of an IEnumerable<T>

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 Source

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])
              do r := (!r - 1) }
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download