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?

+4
source share
6 answers

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

http://research.microsoft.com/en-us/um/cambridge/projects/fsharp/manual/FSharp.Core/Microsoft.FSharp.Collections.Seq.html

// 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) } 
+4
source

Actually, you can use LINQ to solve this problem, for example.

 var subList = list.Skip(x).Take(y); 

where list is IEnumerable

+2
source

You can use the Select extension, which provides an index to create an object containing the index and value, then divide the index by length to put them in groups:

 var x = values.Select((n, i) => new { Index = i, Value = n }).GroupBy(a => a.Index / 3); 
0
source
 IEnumerable<IEnumerable<T>> ContiguousSubseqences<T>(this IEnumerable<T> seq, Func<T,bool> constraint) { int i = 0; foreach (T t in seq) { if (constraint(t)) yield return seq.Skip(i).TakeWhile(constraint); i++; } } 
0
source

Here is a new extension method to do what you want in C #

 static IEnumerable<IEnumerable<T>> Subseqs<T>(this IEnumerable<T> xs, int n) { var cnt = xs.Count() - n; Enumerable.Range(0, cnt < 0 ? 0 : cnt).Select(i => xs.Skip(i).Take(n)); } 
0
source

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.

0
source

All Articles