Select the following N IEnumerable <T> elements
Say you have an 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, that would be pretty easy. There are (S.Length - n + 1) subsequences of length n. For example, "abcdefg" is the length (7), so it means that it has (5) substrings of length (3): "abc", "bcd", "cde", "def", "efg".
But S can be any IEnumerable, so this route is not open. How to use extension methods to solve this problem?
F # has a Seq.windowed library function 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) } For future readers.
Here is a small example.
private static void RunTakeSkipExample() { int takeSize = 10; /* set takeSize to 10 */ /* create 25 exceptions, so 25 / 10 .. means 3 "takes" with sizes of 10, 10 and 5 */ ICollection<ArithmeticException> allArithExceptions = new List<ArithmeticException>(); for (int i = 1; i <= 25; i++) { allArithExceptions.Add(new ArithmeticException(Convert.ToString(i))); } int counter = 0; IEnumerable<ArithmeticException> currentTakeArithExceptions = allArithExceptions.Skip(0).Take(takeSize); while (currentTakeArithExceptions.Any()) { Console.WriteLine("Taking! TakeSize={0}. Counter={1}. Count={2}.", takeSize, (counter + 1), currentTakeArithExceptions.Count()); foreach (ArithmeticException ae in currentTakeArithExceptions) { Console.WriteLine(ae.Message); } currentTakeArithExceptions = allArithExceptions.Skip(++counter * takeSize).Take(takeSize); } } Output:
Taking! TakeSize=10. Counter=1. Count=10. 1 2 3 4 5 6 7 8 9 10 Taking! TakeSize=10. Counter=2. Count=10. 11 12 13 14 15 16 17 18 19 20 Taking! TakeSize=10. Counter=3. Count=5. 21 22 23 24 25 You can see by .Message for each exception to verify that each individual exception has been βacceptedβ.
And now, a quote from the movie!
But I have a very specific skill set; I have acquired over a very long career. Skills that make me a nightmare for people like you.