36 people like it.

Take every Nth element of sequence

A function that takes every Nth element of a sequence where N is passed as an argument. The snippet shows a naive function and a function using IEnumerator directly to provide an efficient implementation.

Composing existing functions

1: 
2: 
3: 
4: 
  let everyNth n seq = 
    seq |> Seq.mapi (fun i el -> el, i)              // Add index to element
        |> Seq.filter (fun (el, i) -> i % n = n - 1) // Take every nth element
        |> Seq.map fst                               // Drop index from the result

Efficient version using enumerator

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
  let everyNth n (input:seq<_>) = 
    seq { use en = input.GetEnumerator()
          // Call MoveNext at most 'n' times (or return false earlier)
          let rec nextN n = 
            if n = 0 then true
            else en.MoveNext() && (nextN (n - 1)) 
          // While we can move n elements forward...
          while nextN n do
            // Retrun each nth element
            yield en.Current }
val everyNth : n:int -> seq:seq<'a> -> seq<'a>

Full name: Script.Simple.everyNth
val n : int
Multiple items
val seq : seq<'a>

--------------------
type seq<'T> = System.Collections.Generic.IEnumerable<'T>

Full name: Microsoft.FSharp.Collections.seq<_>
module Seq

from Microsoft.FSharp.Collections
val mapi : mapping:(int -> 'T -> 'U) -> source:seq<'T> -> seq<'U>

Full name: Microsoft.FSharp.Collections.Seq.mapi
val i : int
val el : 'a
val filter : predicate:('T -> bool) -> source:seq<'T> -> seq<'T>

Full name: Microsoft.FSharp.Collections.Seq.filter
val map : mapping:('T -> 'U) -> source:seq<'T> -> seq<'U>

Full name: Microsoft.FSharp.Collections.Seq.map
val fst : tuple:('T1 * 'T2) -> 'T1

Full name: Microsoft.FSharp.Core.Operators.fst
val everyNth : n:int -> input:seq<'a> -> seq<'a>

Full name: Script.Efficient.everyNth
val input : seq<'a>
Multiple items
val seq : sequence:seq<'T> -> seq<'T>

Full name: Microsoft.FSharp.Core.Operators.seq

--------------------
type seq<'T> = System.Collections.Generic.IEnumerable<'T>

Full name: Microsoft.FSharp.Collections.seq<_>
val en : System.Collections.Generic.IEnumerator<'a>
System.Collections.Generic.IEnumerable.GetEnumerator() : System.Collections.Generic.IEnumerator<'a>
val nextN : (int -> bool)
System.Collections.IEnumerator.MoveNext() : bool
property System.Collections.Generic.IEnumerator.Current: 'a
Raw view Test code New version

More information

Link:http://fssnip.net/1R
Posted:13 years ago
Author:Tomas Petricek
Tags: sequence , seq