0 people like it.

Take value from a sequence only when it changes

Take value from a sequence only when it changes (based on a predicate). Ex: Seq [1;1;1;3;3;3;5;5;5] will result in [3;5]

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
open System.Collections.Generic

//Filter function with accumulator
let filter (acc:'a) (f:('a -> 'b -> bool * 'a)) (s:'b seq) = 
    let rec iter (acc:'a) (e:IEnumerator<'b>) = 
        match e.MoveNext() with
        | false -> Seq.empty 
        | true -> match f acc e.Current with
                  | (true,newAcc) -> seq { yield e.Current; yield! iter newAcc e}
                  | (false,newAcc) -> seq { yield! iter newAcc e}
    iter acc (s.GetEnumerator())

//main function
let skipUntilChange (f : 'a -> 'b) (s : 'a seq) = 
    s |> Seq.skip 1
    |> filter (s |> Seq.head |> f)
        (fun a b -> if a = f b then false,f b else true,f b)

//Example:
[1;1;1;3;3;3;5;5;5] |> skipUntilChange id |> printfn "%A"
namespace System
namespace System.Collections
namespace System.Collections.Generic
val filter : acc:'a -> f:('a -> 'b -> bool * 'a) -> s:seq<'b> -> seq<'b>

Full name: Script.filter
val acc : 'a
val f : ('a -> 'b -> bool * 'a)
type bool = System.Boolean

Full name: Microsoft.FSharp.Core.bool
val s : seq<'b>
Multiple items
val seq : sequence:seq<'T> -> seq<'T>

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

--------------------
type seq<'T> = IEnumerable<'T>

Full name: Microsoft.FSharp.Collections.seq<_>
val iter : ('a -> IEnumerator<'b> -> seq<'b>)
val e : IEnumerator<'b>
type IEnumerator<'T> =
  member Current : 'T

Full name: System.Collections.Generic.IEnumerator<_>
System.Collections.IEnumerator.MoveNext() : bool
module Seq

from Microsoft.FSharp.Collections
val empty<'T> : seq<'T>

Full name: Microsoft.FSharp.Collections.Seq.empty
property IEnumerator.Current: 'b
val newAcc : 'a
IEnumerable.GetEnumerator() : IEnumerator<'b>
val skipUntilChange : f:('a -> 'b) -> s:seq<'a> -> seq<'a> (requires equality)

Full name: Script.skipUntilChange
val f : ('a -> 'b) (requires equality)
val s : seq<'a>
val skip : count:int -> source:seq<'T> -> seq<'T>

Full name: Microsoft.FSharp.Collections.Seq.skip
val head : source:seq<'T> -> 'T

Full name: Microsoft.FSharp.Collections.Seq.head
val a : 'b (requires equality)
val b : 'a
val id : x:'T -> 'T

Full name: Microsoft.FSharp.Core.Operators.id
val printfn : format:Printf.TextWriterFormat<'T> -> 'T

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.printfn
Raw view Test code New version

More information

Link:http://fssnip.net/6H
Posted:12 years ago
Author:Ankur Dhama
Tags: seq , filtering