File tree Expand file tree Collapse file tree 5 files changed +71
-0
lines changed
FSharp.Control.TaskSeq.Test Expand file tree Collapse file tree 5 files changed +71
-0
lines changed Original file line number Diff line number Diff line change 1919 <Compile Include =" TaskSeq.Empty.Tests.fs" />
2020 <Compile Include =" TaskSeq.ExactlyOne.Tests.fs" />
2121 <Compile Include =" TaskSeq.Except.Tests.fs" />
22+ <Compile Include =" TaskSeq.DistinctUntilChanged.Tests.fs" />
2223 <Compile Include =" TaskSeq.Exists.Tests.fs" />
2324 <Compile Include =" TaskSeq.Filter.Tests.fs" />
2425 <Compile Include =" TaskSeq.FindIndex.Tests.fs" />
Original file line number Diff line number Diff line change 1+ module TaskSeq.Tests.DistinctUntilChanged
2+
3+ open Xunit
4+ open FsUnit.Xunit
5+
6+ open FSharp.Control
7+
8+ //
9+ // TaskSeq.distinctUntilChanged
10+ //
11+
12+
13+ module EmptySeq =
14+ [<Fact>]
15+ let ``TaskSeq - distinctUntilChanged with null source raises`` () = assertNullArg <| fun () -> TaskSeq.distinctUntilChanged null
16+
17+ [<Theory; ClassData( typeof< TestEmptyVariants>) >]
18+ let ``TaskSeq - distinctUntilChanged has no effect`` variant = task {
19+ do !
20+ Gen.getEmptyVariant variant
21+ |> TaskSeq.distinctUntilChanged
22+ |> TaskSeq.toListAsync
23+ |> Task.map ( List.isEmpty >> should be True)
24+ }
25+
26+ module Functionality =
27+ [<Fact>]
28+ let ``TaskSeq - distinctUntilChanged should return no consecutive duplicates`` () = task {
29+ let ts =
30+ [ 'A' ; 'A' ; 'B' ; 'Z' ; 'C' ; 'C' ; 'Z' ; 'C' ; 'D' ; 'D' ; 'D' ; 'Z' ]
31+ |> TaskSeq.ofList
32+
33+ let! xs = ts |> TaskSeq.distinctUntilChanged |> TaskSeq.toListAsync
34+
35+ xs
36+ |> List.map string
37+ |> String.concat " "
38+ |> should equal " ABZCZCDZ"
39+ }
Original file line number Diff line number Diff line change @@ -358,6 +358,8 @@ type TaskSeq private () =
358358 static member except itemsToExclude source = Internal.except itemsToExclude source
359359 static member exceptOfSeq itemsToExclude source = Internal.exceptOfSeq itemsToExclude source
360360
361+ static member distinctUntilChanged source = Internal.distinctUntilChanged source
362+
361363 static member forall predicate source = Internal.forall ( Predicate predicate) source
362364 static member forallAsync predicate source = Internal.forall ( PredicateAsync predicate) source
363365
Original file line number Diff line number Diff line change @@ -1297,6 +1297,16 @@ type TaskSeq =
12971297 /// <exception cref =" T:ArgumentNullException " >Thrown when either of the two input task sequences is null.</exception >
12981298 static member exceptOfSeq < 'T when 'T : equality > : itemsToExclude : seq < 'T > -> source : TaskSeq < 'T > -> TaskSeq < 'T >
12991299
1300+ /// <summary >
1301+ /// Returns a new task sequence without consecutive duplicate elements.
1302+ /// </summary >
1303+ ///
1304+ /// <param name =" source " >The input task sequence whose consecutive duplicates will be removed.</param >
1305+ /// <returns >A sequence without consecutive duplicates elements.</returns >
1306+ ///
1307+ /// <exception cref =" T:ArgumentNullException " >Thrown when the input task sequences is null.</exception >
1308+ static member distinctUntilChanged < 'T when 'T : equality > : source : TaskSeq < 'T > -> TaskSeq < 'T >
1309+
13001310 /// <summary >
13011311 /// Combines the two task sequences into a new task sequence of pairs. The two sequences need not have equal lengths:
13021312 /// when one sequence is exhausted any remaining elements in the other sequence are ignored.
Original file line number Diff line number Diff line change @@ -1097,3 +1097,22 @@ module internal TaskSeqInternal =
10971097 go <- step
10981098
10991099 }
1100+
1101+ let distinctUntilChanged ( source : TaskSeq < _ >) =
1102+ checkNonNull ( nameof source) source
1103+
1104+ taskSeq {
1105+ let mutable maybePrevious = ValueNone
1106+
1107+ for current in source do
1108+ match maybePrevious with
1109+ | ValueNone ->
1110+ yield current
1111+ maybePrevious <- ValueSome current
1112+ | ValueSome previous ->
1113+ if previous = current then
1114+ () // skip
1115+ else
1116+ yield current
1117+ maybePrevious <- ValueSome current
1118+ }
You can’t perform that action at this time.
0 commit comments