diff --git a/src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Collections/ArrayModule.fs b/src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Collections/ArrayModule.fs index 608e8cf3ef2..d0b440ea7d2 100644 --- a/src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Collections/ArrayModule.fs +++ b/src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Collections/ArrayModule.fs @@ -144,6 +144,57 @@ type ArrayModule() = () + [] + member this.ChunkBySize() = + + // int Seq + Assert.AreEqual([| [|1..4|]; [|5..8|] |], Array.chunkBySize 4 [|1..8|]) + Assert.AreEqual([| [|1..4|]; [|5..8|]; [|9..10|] |], Array.chunkBySize 4 [|1..10|]) + Assert.AreEqual([| [|1|]; [|2|]; [|3|]; [|4|] |], Array.chunkBySize 1 [|1..4|]) + + // string Seq + Assert.AreEqual([| [|"a"; "b"|]; [|"c";"d"|]; [|"e"|] |], Array.chunkBySize 2 [|"a";"b";"c";"d";"e"|]) + + // empty Seq + Assert.AreEqual([||], Array.chunkBySize 3 [||]) + + // null Seq + let nullArr:_[] = null + CheckThrowsArgumentNullException (fun () -> Array.chunkBySize 3 nullArr |> ignore) + + // invalidArg + CheckThrowsArgumentException (fun () -> Array.chunkBySize 0 [|1..10|] |> ignore) + CheckThrowsArgumentException (fun () -> Array.chunkBySize -1 [|1..10|] |> ignore) + + () + + [] + member this.SplitInto() = + + // int array + Assert.AreEqual([| [|1..4|]; [|5..7|]; [|8..10|] |], Array.splitInto 3 [|1..10|]) + Assert.AreEqual([| [|1..4|]; [|5..8|]; [|9..11|] |], Array.splitInto 3 [|1..11|]) + Assert.AreEqual([| [|1..4|]; [|5..8|]; [|9..12|] |], Array.splitInto 3 [|1..12|]) + + Assert.AreEqual([| [|1..2|]; [|3|]; [|4|]; [|5|] |], Array.splitInto 4 [|1..5|]) + Assert.AreEqual([| [|1|]; [|2|]; [|3|]; [|4|] |], Array.splitInto 20 [|1..4|]) + + // string array + Assert.AreEqual([| [|"a"; "b"|]; [|"c";"d"|]; [|"e"|] |], Array.splitInto 3 [|"a";"b";"c";"d";"e"|]) + + // empty array + Assert.AreEqual([| |], Array.splitInto 3 [| |]) + + // null array + let nullArr:_[] = null + CheckThrowsArgumentNullException (fun () -> Array.splitInto 3 nullArr |> ignore) + + // invalidArg + CheckThrowsArgumentException (fun () -> Array.splitInto 0 [|1..10|] |> ignore) + CheckThrowsArgumentException (fun () -> Array.splitInto -1 [|1..10|] |> ignore) + + () + [] member this.distinct() = // distinct should work on empty array diff --git a/src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Collections/ListModule.fs b/src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Collections/ListModule.fs index 5851f74d99c..481decfffa7 100644 --- a/src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Collections/ListModule.fs +++ b/src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Collections/ListModule.fs @@ -107,7 +107,50 @@ type ListModule() = Assert.AreEqual(22.476666666666666666666666667M, averageOfDecimal) () - + + [] + member this.ChunkBySize() = + + // int list + Assert.AreEqual([ [1..4]; [5..8] ], List.chunkBySize 4 [1..8]) + Assert.AreEqual([ [1..4]; [5..8]; [9..10] ], List.chunkBySize 4 [1..10]) + Assert.AreEqual([ [1]; [2]; [3]; [4] ], List.chunkBySize 1 [1..4]) + + // string list + Assert.AreEqual([ ["a"; "b"]; ["c";"d"]; ["e"] ], List.chunkBySize 2 ["a";"b";"c";"d";"e"]) + + // empty list + Assert.AreEqual([], List.chunkBySize 3 []) + + // invalidArg + CheckThrowsArgumentException (fun () -> List.chunkBySize 0 [1..10] |> ignore) + CheckThrowsArgumentException (fun () -> List.chunkBySize -1 [1..10] |> ignore) + + () + + [] + member this.SplitInto() = + + // int list + Assert.AreEqual([ [1..4]; [5..7]; [8..10] ], List.splitInto 3 [1..10]) + Assert.AreEqual([ [1..4]; [5..8]; [9..11] ], List.splitInto 3 [1..11]) + Assert.AreEqual([ [1..4]; [5..8]; [9..12] ], List.splitInto 3 [1..12]) + + Assert.AreEqual([ [1..2]; [3]; [4]; [5] ], List.splitInto 4 [1..5]) + Assert.AreEqual([ [1]; [2]; [3]; [4] ], List.splitInto 20 [1..4]) + + // string list + Assert.AreEqual([ ["a"; "b"]; ["c";"d"]; ["e"] ], List.splitInto 3 ["a";"b";"c";"d";"e"]) + + // empty list + Assert.AreEqual([], List.splitInto 3 []) + + // invalidArg + CheckThrowsArgumentException (fun () -> List.splitInto 0 [1..10] |> ignore) + CheckThrowsArgumentException (fun () -> List.splitInto -1 [1..10] |> ignore) + + () + [] member this.distinct() = // distinct should work on empty list diff --git a/src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Collections/SeqModule.fs b/src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Collections/SeqModule.fs index 3caae6d79d4..71105a8a3b1 100644 --- a/src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Collections/SeqModule.fs +++ b/src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Collections/SeqModule.fs @@ -302,7 +302,74 @@ type SeqModule() = CheckThrowsArgumentNullException (fun () -> Seq.choose funcInt nullSeq |> ignore) () - + + [] + member this.ChunkBySize() = + + let verify expected actual = + Seq.zip expected actual + |> Seq.iter ((<||) VerifySeqsEqual) + + // int Seq + verify [[1..4];[5..8]] <| Seq.chunkBySize 4 {1..8} + verify [[1..4];[5..8];[9..10]] <| Seq.chunkBySize 4 {1..10} + verify [[1]; [2]; [3]; [4]] <| Seq.chunkBySize 1 {1..4} + + Seq.chunkBySize 2 (Seq.initInfinite id) + |> Seq.take 3 + |> verify [[0;1];[2;3];[4;5]] + + Seq.chunkBySize 1 (Seq.initInfinite id) + |> Seq.take 5 + |> verify [[0];[1];[2];[3];[4]] + + // string Seq + verify [["a"; "b"];["c";"d"];["e"]] <| Seq.chunkBySize 2 ["a";"b";"c";"d";"e"] + + // empty Seq + verify Seq.empty <| Seq.chunkBySize 3 Seq.empty + + // null Seq + let nullSeq:seq<_> = null + CheckThrowsArgumentNullException (fun () -> Seq.chunkBySize 3 nullSeq |> ignore) + + // invalidArg + CheckThrowsArgumentException (fun () -> Seq.chunkBySize 0 {1..10} |> ignore) + CheckThrowsArgumentException (fun () -> Seq.chunkBySize -1 {1..10} |> ignore) + + () + + [] + member this.SplitInto() = + + let verify expected actual = + Seq.zip expected actual + |> Seq.iter ((<||) VerifySeqsEqual) + + // int Seq + Seq.splitInto 3 {1..10} |> verify (seq [ {1..4}; {5..7}; {8..10} ]) + Seq.splitInto 3 {1..11} |> verify (seq [ {1..4}; {5..8}; {9..11} ]) + Seq.splitInto 3 {1..12} |> verify (seq [ {1..4}; {5..8}; {9..12} ]) + + Seq.splitInto 4 {1..5} |> verify (seq [ [1..2]; [3]; [4]; [5] ]) + Seq.splitInto 20 {1..4} |> verify (seq [ [1]; [2]; [3]; [4] ]) + + // string Seq + Seq.splitInto 3 ["a";"b";"c";"d";"e"] |> verify ([ ["a"; "b"]; ["c";"d"]; ["e"] ]) + + // empty Seq + VerifySeqsEqual [] <| Seq.splitInto 3 [] + + // null Seq + let nullSeq:seq<_> = null + CheckThrowsArgumentNullException (fun () -> Seq.splitInto 3 nullSeq |> ignore) + + // invalidArg + CheckThrowsArgumentException (fun () -> Seq.splitInto 0 [1..10] |> ignore) + CheckThrowsArgumentException (fun () -> Seq.splitInto -1 [1..10] |> ignore) + + () + [] member this.Compare() = diff --git a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.net40.fs b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.net40.fs index 09ee5847af1..c2acc2e7474 100644 --- a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.net40.fs +++ b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.net40.fs @@ -173,6 +173,8 @@ Microsoft.FSharp.Collections.ArrayModule: T[] Truncate[T](Int32, T[]) Microsoft.FSharp.Collections.ArrayModule: T[] Unfold[T,TState](Microsoft.FSharp.Core.FSharpFunc`2[TState,Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`2[T,TState]]], TState) Microsoft.FSharp.Collections.ArrayModule: T[] Where[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], T[]) Microsoft.FSharp.Collections.ArrayModule: T[] ZeroCreate[T](Int32) +Microsoft.FSharp.Collections.ArrayModule: T[][] ChunkBySize[T](Int32, T[]) +Microsoft.FSharp.Collections.ArrayModule: T[][] SplitInto[T](Int32, T[]) Microsoft.FSharp.Collections.ArrayModule: T[][] Windowed[T](Int32, T[]) Microsoft.FSharp.Collections.ArrayModule: Void CopyTo[T](T[], Int32, T[], Int32, Int32) Microsoft.FSharp.Collections.ArrayModule: Void Fill[T](T[], Int32, Int32, T) @@ -289,6 +291,8 @@ Microsoft.FSharp.Collections.ListModule: Int32 FindIndexBack[T](Microsoft.FSharp Microsoft.FSharp.Collections.ListModule: Int32 FindIndex[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.FSharpList`1[T]) Microsoft.FSharp.Collections.ListModule: Int32 GetHashCode() Microsoft.FSharp.Collections.ListModule: Int32 Length[T](Microsoft.FSharp.Collections.FSharpList`1[T]) +Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[Microsoft.FSharp.Collections.FSharpList`1[T]] ChunkBySize[T](Int32, Microsoft.FSharp.Collections.FSharpList`1[T]) +Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[Microsoft.FSharp.Collections.FSharpList`1[T]] SplitInto[T](Int32, Microsoft.FSharp.Collections.FSharpList`1[T]) Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[Microsoft.FSharp.Collections.FSharpList`1[T]] Windowed[T](Int32, Microsoft.FSharp.Collections.FSharpList`1[T]) Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`2[System.Int32,T]] Indexed[T](Microsoft.FSharp.Collections.FSharpList`1[T]) Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`2[T,T]] Pairwise[T](Microsoft.FSharp.Collections.FSharpList`1[T]) @@ -441,6 +445,8 @@ Microsoft.FSharp.Collections.SeqModule: System.Collections.Generic.IEnumerable`1 Microsoft.FSharp.Collections.SeqModule: System.Collections.Generic.IEnumerable`1[TResult] Map[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.SeqModule: System.Collections.Generic.IEnumerable`1[TState] ScanBack[T,TState](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TState,TState]], System.Collections.Generic.IEnumerable`1[T], TState) Microsoft.FSharp.Collections.SeqModule: System.Collections.Generic.IEnumerable`1[TState] Scan[T,TState](Microsoft.FSharp.Core.FSharpFunc`2[TState,Microsoft.FSharp.Core.FSharpFunc`2[T,TState]], TState, System.Collections.Generic.IEnumerable`1[T]) +Microsoft.FSharp.Collections.SeqModule: System.Collections.Generic.IEnumerable`1[T[]] ChunkBySize[T](Int32, System.Collections.Generic.IEnumerable`1[T]) +Microsoft.FSharp.Collections.SeqModule: System.Collections.Generic.IEnumerable`1[T[]] SplitInto[T](Int32, System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.SeqModule: System.Collections.Generic.IEnumerable`1[T[]] Windowed[T](Int32, System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.SeqModule: System.Collections.Generic.IEnumerable`1[T] Append[T](System.Collections.Generic.IEnumerable`1[T], System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.SeqModule: System.Collections.Generic.IEnumerable`1[T] Cache[T](System.Collections.Generic.IEnumerable`1[T]) diff --git a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.portable259.fs b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.portable259.fs index 2352f7c5768..01a8aca3f6f 100644 --- a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.portable259.fs +++ b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.portable259.fs @@ -160,6 +160,8 @@ Microsoft.FSharp.Collections.ArrayModule: T[] Truncate[T](Int32, T[]) Microsoft.FSharp.Collections.ArrayModule: T[] Unfold[T,TState](Microsoft.FSharp.Core.FSharpFunc`2[TState,Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`2[T,TState]]], TState) Microsoft.FSharp.Collections.ArrayModule: T[] Where[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], T[]) Microsoft.FSharp.Collections.ArrayModule: T[] ZeroCreate[T](Int32) +Microsoft.FSharp.Collections.ArrayModule: T[][] ChunkBySize[T](Int32, T[]) +Microsoft.FSharp.Collections.ArrayModule: T[][] SplitInto[T](Int32, T[]) Microsoft.FSharp.Collections.ArrayModule: T[][] Windowed[T](Int32, T[]) Microsoft.FSharp.Collections.ArrayModule: Void CopyTo[T](T[], Int32, T[], Int32, Int32) Microsoft.FSharp.Collections.ArrayModule: Void Fill[T](T[], Int32, Int32, T) @@ -276,6 +278,8 @@ Microsoft.FSharp.Collections.ListModule: Int32 FindIndexBack[T](Microsoft.FSharp Microsoft.FSharp.Collections.ListModule: Int32 FindIndex[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.FSharpList`1[T]) Microsoft.FSharp.Collections.ListModule: Int32 GetHashCode() Microsoft.FSharp.Collections.ListModule: Int32 Length[T](Microsoft.FSharp.Collections.FSharpList`1[T]) +Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[Microsoft.FSharp.Collections.FSharpList`1[T]] ChunkBySize[T](Int32, Microsoft.FSharp.Collections.FSharpList`1[T]) +Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[Microsoft.FSharp.Collections.FSharpList`1[T]] SplitInto[T](Int32, Microsoft.FSharp.Collections.FSharpList`1[T]) Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[Microsoft.FSharp.Collections.FSharpList`1[T]] Windowed[T](Int32, Microsoft.FSharp.Collections.FSharpList`1[T]) Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`2[System.Int32,T]] Indexed[T](Microsoft.FSharp.Collections.FSharpList`1[T]) Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`2[T,T]] Pairwise[T](Microsoft.FSharp.Collections.FSharpList`1[T]) @@ -428,6 +432,8 @@ Microsoft.FSharp.Collections.SeqModule: System.Collections.Generic.IEnumerable`1 Microsoft.FSharp.Collections.SeqModule: System.Collections.Generic.IEnumerable`1[TResult] Map[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.SeqModule: System.Collections.Generic.IEnumerable`1[TState] ScanBack[T,TState](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TState,TState]], System.Collections.Generic.IEnumerable`1[T], TState) Microsoft.FSharp.Collections.SeqModule: System.Collections.Generic.IEnumerable`1[TState] Scan[T,TState](Microsoft.FSharp.Core.FSharpFunc`2[TState,Microsoft.FSharp.Core.FSharpFunc`2[T,TState]], TState, System.Collections.Generic.IEnumerable`1[T]) +Microsoft.FSharp.Collections.SeqModule: System.Collections.Generic.IEnumerable`1[T[]] ChunkBySize[T](Int32, System.Collections.Generic.IEnumerable`1[T]) +Microsoft.FSharp.Collections.SeqModule: System.Collections.Generic.IEnumerable`1[T[]] SplitInto[T](Int32, System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.SeqModule: System.Collections.Generic.IEnumerable`1[T[]] Windowed[T](Int32, System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.SeqModule: System.Collections.Generic.IEnumerable`1[T] Append[T](System.Collections.Generic.IEnumerable`1[T], System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.SeqModule: System.Collections.Generic.IEnumerable`1[T] Cache[T](System.Collections.Generic.IEnumerable`1[T]) diff --git a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.portable47.fs b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.portable47.fs index 98e6d2d3cbf..c441cddafbd 100644 --- a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.portable47.fs +++ b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.portable47.fs @@ -157,6 +157,8 @@ Microsoft.FSharp.Collections.ArrayModule: T[] Truncate[T](Int32, T[]) Microsoft.FSharp.Collections.ArrayModule: T[] Unfold[T,TState](Microsoft.FSharp.Core.FSharpFunc`2[TState,Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`2[T,TState]]], TState) Microsoft.FSharp.Collections.ArrayModule: T[] Where[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], T[]) Microsoft.FSharp.Collections.ArrayModule: T[] ZeroCreate[T](Int32) +Microsoft.FSharp.Collections.ArrayModule: T[][] ChunkBySize[T](Int32, T[]) +Microsoft.FSharp.Collections.ArrayModule: T[][] SplitInto[T](Int32, T[]) Microsoft.FSharp.Collections.ArrayModule: T[][] Windowed[T](Int32, T[]) Microsoft.FSharp.Collections.ArrayModule: Void CopyTo[T](T[], Int32, T[], Int32, Int32) Microsoft.FSharp.Collections.ArrayModule: Void Fill[T](T[], Int32, Int32, T) @@ -273,6 +275,8 @@ Microsoft.FSharp.Collections.ListModule: Int32 FindIndexBack[T](Microsoft.FSharp Microsoft.FSharp.Collections.ListModule: Int32 FindIndex[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.FSharpList`1[T]) Microsoft.FSharp.Collections.ListModule: Int32 GetHashCode() Microsoft.FSharp.Collections.ListModule: Int32 Length[T](Microsoft.FSharp.Collections.FSharpList`1[T]) +Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[Microsoft.FSharp.Collections.FSharpList`1[T]] ChunkBySize[T](Int32, Microsoft.FSharp.Collections.FSharpList`1[T]) +Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[Microsoft.FSharp.Collections.FSharpList`1[T]] SplitInto[T](Int32, Microsoft.FSharp.Collections.FSharpList`1[T]) Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[Microsoft.FSharp.Collections.FSharpList`1[T]] Windowed[T](Int32, Microsoft.FSharp.Collections.FSharpList`1[T]) Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`2[System.Int32,T]] Indexed[T](Microsoft.FSharp.Collections.FSharpList`1[T]) Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`2[T,T]] Pairwise[T](Microsoft.FSharp.Collections.FSharpList`1[T]) @@ -425,6 +429,8 @@ Microsoft.FSharp.Collections.SeqModule: System.Collections.Generic.IEnumerable`1 Microsoft.FSharp.Collections.SeqModule: System.Collections.Generic.IEnumerable`1[TResult] Map[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.SeqModule: System.Collections.Generic.IEnumerable`1[TState] ScanBack[T,TState](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TState,TState]], System.Collections.Generic.IEnumerable`1[T], TState) Microsoft.FSharp.Collections.SeqModule: System.Collections.Generic.IEnumerable`1[TState] Scan[T,TState](Microsoft.FSharp.Core.FSharpFunc`2[TState,Microsoft.FSharp.Core.FSharpFunc`2[T,TState]], TState, System.Collections.Generic.IEnumerable`1[T]) +Microsoft.FSharp.Collections.SeqModule: System.Collections.Generic.IEnumerable`1[T[]] ChunkBySize[T](Int32, System.Collections.Generic.IEnumerable`1[T]) +Microsoft.FSharp.Collections.SeqModule: System.Collections.Generic.IEnumerable`1[T[]] SplitInto[T](Int32, System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.SeqModule: System.Collections.Generic.IEnumerable`1[T[]] Windowed[T](Int32, System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.SeqModule: System.Collections.Generic.IEnumerable`1[T] Append[T](System.Collections.Generic.IEnumerable`1[T], System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.SeqModule: System.Collections.Generic.IEnumerable`1[T] Cache[T](System.Collections.Generic.IEnumerable`1[T]) diff --git a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.portable7.fs b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.portable7.fs index 95ab02adab3..21d15322e8e 100644 --- a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.portable7.fs +++ b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.portable7.fs @@ -173,6 +173,8 @@ Microsoft.FSharp.Collections.ArrayModule: T[] Truncate[T](Int32, T[]) Microsoft.FSharp.Collections.ArrayModule: T[] Unfold[T,TState](Microsoft.FSharp.Core.FSharpFunc`2[TState,Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`2[T,TState]]], TState) Microsoft.FSharp.Collections.ArrayModule: T[] Where[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], T[]) Microsoft.FSharp.Collections.ArrayModule: T[] ZeroCreate[T](Int32) +Microsoft.FSharp.Collections.ArrayModule: T[][] ChunkBySize[T](Int32, T[]) +Microsoft.FSharp.Collections.ArrayModule: T[][] SplitInto[T](Int32, T[]) Microsoft.FSharp.Collections.ArrayModule: T[][] Windowed[T](Int32, T[]) Microsoft.FSharp.Collections.ArrayModule: Void CopyTo[T](T[], Int32, T[], Int32, Int32) Microsoft.FSharp.Collections.ArrayModule: Void Fill[T](T[], Int32, Int32, T) @@ -289,6 +291,8 @@ Microsoft.FSharp.Collections.ListModule: Int32 FindIndexBack[T](Microsoft.FSharp Microsoft.FSharp.Collections.ListModule: Int32 FindIndex[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.FSharpList`1[T]) Microsoft.FSharp.Collections.ListModule: Int32 GetHashCode() Microsoft.FSharp.Collections.ListModule: Int32 Length[T](Microsoft.FSharp.Collections.FSharpList`1[T]) +Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[Microsoft.FSharp.Collections.FSharpList`1[T]] ChunkBySize[T](Int32, Microsoft.FSharp.Collections.FSharpList`1[T]) +Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[Microsoft.FSharp.Collections.FSharpList`1[T]] SplitInto[T](Int32, Microsoft.FSharp.Collections.FSharpList`1[T]) Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[Microsoft.FSharp.Collections.FSharpList`1[T]] Windowed[T](Int32, Microsoft.FSharp.Collections.FSharpList`1[T]) Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`2[System.Int32,T]] Indexed[T](Microsoft.FSharp.Collections.FSharpList`1[T]) Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`2[T,T]] Pairwise[T](Microsoft.FSharp.Collections.FSharpList`1[T]) @@ -441,6 +445,8 @@ Microsoft.FSharp.Collections.SeqModule: System.Collections.Generic.IEnumerable`1 Microsoft.FSharp.Collections.SeqModule: System.Collections.Generic.IEnumerable`1[TResult] Map[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.SeqModule: System.Collections.Generic.IEnumerable`1[TState] ScanBack[T,TState](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TState,TState]], System.Collections.Generic.IEnumerable`1[T], TState) Microsoft.FSharp.Collections.SeqModule: System.Collections.Generic.IEnumerable`1[TState] Scan[T,TState](Microsoft.FSharp.Core.FSharpFunc`2[TState,Microsoft.FSharp.Core.FSharpFunc`2[T,TState]], TState, System.Collections.Generic.IEnumerable`1[T]) +Microsoft.FSharp.Collections.SeqModule: System.Collections.Generic.IEnumerable`1[T[]] ChunkBySize[T](Int32, System.Collections.Generic.IEnumerable`1[T]) +Microsoft.FSharp.Collections.SeqModule: System.Collections.Generic.IEnumerable`1[T[]] SplitInto[T](Int32, System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.SeqModule: System.Collections.Generic.IEnumerable`1[T[]] Windowed[T](Int32, System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.SeqModule: System.Collections.Generic.IEnumerable`1[T] Append[T](System.Collections.Generic.IEnumerable`1[T], System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.SeqModule: System.Collections.Generic.IEnumerable`1[T] Cache[T](System.Collections.Generic.IEnumerable`1[T]) diff --git a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.portable78.fs b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.portable78.fs index bef9e6becae..4bcf539f324 100644 --- a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.portable78.fs +++ b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.portable78.fs @@ -160,6 +160,8 @@ Microsoft.FSharp.Collections.ArrayModule: T[] Truncate[T](Int32, T[]) Microsoft.FSharp.Collections.ArrayModule: T[] Unfold[T,TState](Microsoft.FSharp.Core.FSharpFunc`2[TState,Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`2[T,TState]]], TState) Microsoft.FSharp.Collections.ArrayModule: T[] Where[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], T[]) Microsoft.FSharp.Collections.ArrayModule: T[] ZeroCreate[T](Int32) +Microsoft.FSharp.Collections.ArrayModule: T[][] ChunkBySize[T](Int32, T[]) +Microsoft.FSharp.Collections.ArrayModule: T[][] SplitInto[T](Int32, T[]) Microsoft.FSharp.Collections.ArrayModule: T[][] Windowed[T](Int32, T[]) Microsoft.FSharp.Collections.ArrayModule: Void CopyTo[T](T[], Int32, T[], Int32, Int32) Microsoft.FSharp.Collections.ArrayModule: Void Fill[T](T[], Int32, Int32, T) @@ -276,6 +278,8 @@ Microsoft.FSharp.Collections.ListModule: Int32 FindIndexBack[T](Microsoft.FSharp Microsoft.FSharp.Collections.ListModule: Int32 FindIndex[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.FSharpList`1[T]) Microsoft.FSharp.Collections.ListModule: Int32 GetHashCode() Microsoft.FSharp.Collections.ListModule: Int32 Length[T](Microsoft.FSharp.Collections.FSharpList`1[T]) +Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[Microsoft.FSharp.Collections.FSharpList`1[T]] ChunkBySize[T](Int32, Microsoft.FSharp.Collections.FSharpList`1[T]) +Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[Microsoft.FSharp.Collections.FSharpList`1[T]] SplitInto[T](Int32, Microsoft.FSharp.Collections.FSharpList`1[T]) Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[Microsoft.FSharp.Collections.FSharpList`1[T]] Windowed[T](Int32, Microsoft.FSharp.Collections.FSharpList`1[T]) Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`2[System.Int32,T]] Indexed[T](Microsoft.FSharp.Collections.FSharpList`1[T]) Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`2[T,T]] Pairwise[T](Microsoft.FSharp.Collections.FSharpList`1[T]) @@ -428,6 +432,8 @@ Microsoft.FSharp.Collections.SeqModule: System.Collections.Generic.IEnumerable`1 Microsoft.FSharp.Collections.SeqModule: System.Collections.Generic.IEnumerable`1[TResult] Map[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.SeqModule: System.Collections.Generic.IEnumerable`1[TState] ScanBack[T,TState](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TState,TState]], System.Collections.Generic.IEnumerable`1[T], TState) Microsoft.FSharp.Collections.SeqModule: System.Collections.Generic.IEnumerable`1[TState] Scan[T,TState](Microsoft.FSharp.Core.FSharpFunc`2[TState,Microsoft.FSharp.Core.FSharpFunc`2[T,TState]], TState, System.Collections.Generic.IEnumerable`1[T]) +Microsoft.FSharp.Collections.SeqModule: System.Collections.Generic.IEnumerable`1[T[]] ChunkBySize[T](Int32, System.Collections.Generic.IEnumerable`1[T]) +Microsoft.FSharp.Collections.SeqModule: System.Collections.Generic.IEnumerable`1[T[]] SplitInto[T](Int32, System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.SeqModule: System.Collections.Generic.IEnumerable`1[T[]] Windowed[T](Int32, System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.SeqModule: System.Collections.Generic.IEnumerable`1[T] Append[T](System.Collections.Generic.IEnumerable`1[T], System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.SeqModule: System.Collections.Generic.IEnumerable`1[T] Cache[T](System.Collections.Generic.IEnumerable`1[T]) diff --git a/src/fsharp/FSharp.Core/array.fs b/src/fsharp/FSharp.Core/array.fs index d667be92321..57e023123a7 100644 --- a/src/fsharp/FSharp.Core/array.fs +++ b/src/fsharp/FSharp.Core/array.fs @@ -570,6 +570,30 @@ namespace Microsoft.FSharp.Collections res.[i] <- Microsoft.FSharp.Primitives.Basics.Array.subUnchecked i windowSize array res + [] + let chunkBySize chunkSize (array:'T[]) = + checkNonNull "array" array + if chunkSize <= 0 then invalidArg "chunkSize" (SR.GetString(SR.inputMustBePositive)) + let len = array.Length + if len = 0 then + [| |] + else if chunkSize > len then + [| copy array |] + else + let chunkCount = (len - 1) / chunkSize + 1 + let res = Microsoft.FSharp.Primitives.Basics.Array.zeroCreateUnchecked chunkCount : 'T[][] + for i = 0 to len / chunkSize - 1 do + res.[i] <- Microsoft.FSharp.Primitives.Basics.Array.subUnchecked (i * chunkSize) chunkSize array + if len % chunkCount <> 0 then + res.[chunkCount - 1] <- Microsoft.FSharp.Primitives.Basics.Array.subUnchecked ((chunkCount - 1) * chunkSize) (len % chunkSize) array + res + + [] + let splitInto count (array:_[]) = + checkNonNull "array" array + if count <= 0 then invalidArg "count" (SR.GetString(SR.inputMustBePositive)) + Microsoft.FSharp.Primitives.Basics.Array.splitInto count array + [] let zip (array1: _[]) (array2: _[]) = checkNonNull "array1" array1 diff --git a/src/fsharp/FSharp.Core/array.fsi b/src/fsharp/FSharp.Core/array.fsi index ad8af42c16c..a683eaeeba7 100644 --- a/src/fsharp/FSharp.Core/array.fsi +++ b/src/fsharp/FSharp.Core/array.fsi @@ -174,6 +174,15 @@ namespace Microsoft.FSharp.Collections [] val choose: chooser:('T -> 'U option) -> array:'T[] -> 'U[] + /// Divides the input array into chunks of size at most chunkSize. + /// The maximum size of each chunk. + /// The input array. + /// The array divided into chunks. + /// Thrown when the input array is null. + /// Thrown when chunkSize is not positive. + [] + val chunkBySize: chunkSize:int -> array:'T[] -> 'T[][] + /// Returns an array that contains no duplicate entries according to generic hash and /// equality comparisons on the entries. /// If an element occurs multiple times in the array then the later occurrences are discarded. @@ -199,6 +208,15 @@ namespace Microsoft.FSharp.Collections [] val distinctBy: projection:('T -> 'Key) -> array:'T[] -> 'T[] when 'Key : equality + /// Splits the input array into at most count chunks. + /// The maximum number of chunks. + /// The input array. + /// The array split into chunks. + /// Thrown when the input array is null. + /// Thrown when count is not positive. + [] + val splitInto: count:int -> array:'T[] -> 'T[][] + /// Returns an empty array of the given type. /// The empty array. [] diff --git a/src/fsharp/FSharp.Core/list.fs b/src/fsharp/FSharp.Core/list.fs index 6bdf22afdde..541e5e31fc3 100644 --- a/src/fsharp/FSharp.Core/list.fs +++ b/src/fsharp/FSharp.Core/list.fs @@ -471,6 +471,12 @@ namespace Microsoft.FSharp.Collections [] let windowed n x = Microsoft.FSharp.Primitives.Basics.List.windowed n x + [] + let chunkBySize chunkSize list = Microsoft.FSharp.Primitives.Basics.List.chunkBySize chunkSize list + + [] + let splitInto count list = Microsoft.FSharp.Primitives.Basics.List.splitInto count list + [] let zip x1 x2 = Microsoft.FSharp.Primitives.Basics.List.zip x1 x2 diff --git a/src/fsharp/FSharp.Core/list.fsi b/src/fsharp/FSharp.Core/list.fsi index 6054fd90331..fe1a1497508 100644 --- a/src/fsharp/FSharp.Core/list.fsi +++ b/src/fsharp/FSharp.Core/list.fsi @@ -54,6 +54,14 @@ namespace Microsoft.FSharp.Collections [] val choose: chooser:('T -> 'U option) -> list:'T list -> 'U list + /// Divides the input list into chunks of size at most chunkSize. + /// The maximum size of each chunk. + /// The input list. + /// The list divided into chunks. + /// Thrown when chunkSize is not positive. + [] + val chunkBySize: chunkSize:int -> list:'T list -> 'T list list + /// For each element of the list, applies the given function. Concatenates all the results and return the combined list. /// The function to transform each input element into a sublist to be concatenated. /// The input list. @@ -120,6 +128,14 @@ namespace Microsoft.FSharp.Collections [] val countBy : projection:('T -> 'Key) -> list:'T list -> ('Key * int) list when 'Key : equality + /// Splits the input list into at most count chunks. + /// The maximum number of chunks. + /// The input list. + /// The list split into chunks. + /// Thrown when count is not positive. + [] + val splitInto: count:int -> list:'T list -> 'T list list + /// Returns an empty list of the given type. [] [] diff --git a/src/fsharp/FSharp.Core/local.fs b/src/fsharp/FSharp.Core/local.fs index 323d17e8976..0b3b0a434bf 100644 --- a/src/fsharp/FSharp.Core/local.fs +++ b/src/fsharp/FSharp.Core/local.fs @@ -542,6 +542,59 @@ module internal List = windowedToFreshConsTail cons windowSize (len - windowSize) list.Tail cons + let rec chunkBySizeToFreshConsTail chunkCons resCons chunkSize i list = + match list with + | [] -> + setFreshConsTail chunkCons [] + setFreshConsTail resCons [] + | h::t -> + let cons = freshConsNoTail h + if i = chunkSize then + setFreshConsTail chunkCons [] + let newResCons = freshConsNoTail cons + setFreshConsTail resCons newResCons + chunkBySizeToFreshConsTail cons newResCons chunkSize 1 t + else + setFreshConsTail chunkCons cons + chunkBySizeToFreshConsTail cons resCons chunkSize (i+1) t + + let chunkBySize chunkSize list = + if chunkSize <= 0 then invalidArg "chunkSize" (SR.GetString(SR.inputMustBePositive)) + match list with + | [] -> [] + | head::tail -> + let chunkCons = freshConsNoTail head + let res = freshConsNoTail chunkCons + chunkBySizeToFreshConsTail chunkCons res chunkSize 1 tail + res + + let rec splitIntoToFreshConsTail chunkCons resCons lenDivCount lenModCount i j list = + match list with + | [] -> + setFreshConsTail chunkCons [] + setFreshConsTail resCons [] + | h::t -> + let cons = freshConsNoTail h + if (i < lenModCount && j = lenDivCount + 1) || (i >= lenModCount && j = lenDivCount) then + setFreshConsTail chunkCons [] + let newResCons = freshConsNoTail cons + setFreshConsTail resCons newResCons + splitIntoToFreshConsTail cons newResCons lenDivCount lenModCount (i + 1) 1 t + else + setFreshConsTail chunkCons cons + splitIntoToFreshConsTail cons resCons lenDivCount lenModCount i (j + 1) t + + let splitInto count (list: _ list) = + if count <= 0 then invalidArg "count" (SR.GetString(SR.inputMustBePositive)) + match list.Length with + | 0 -> [] + | len -> + let chunkCons = freshConsNoTail list.Head + let res = freshConsNoTail chunkCons + let count = min len count + splitIntoToFreshConsTail chunkCons res (len / count) (len % count) 0 1 list.Tail + res + // optimized mutation-based implementation. This code is only valid in fslib, where mutation of private // tail cons cells is permitted in carefully written library code. let rec zipToFreshConsTail cons xs1 xs2 = @@ -868,3 +921,20 @@ module internal Array = else Array.Copy(array, startIndex, res, 0, count) res + + let splitInto count (array : 'T[]) = + let len = array.Length + if len = 0 then + [| |] + else + let count = min count len + let res = zeroCreateUnchecked count : 'T[][] + let minChunkSize = len / count + let startIndex = ref 0 + for i = 0 to len % count - 1 do + res.[i] <- subUnchecked !startIndex (minChunkSize + 1) array + startIndex := !startIndex + minChunkSize + 1 + for i = len % count to count - 1 do + res.[i] <- subUnchecked !startIndex minChunkSize array + startIndex := !startIndex + minChunkSize + res diff --git a/src/fsharp/FSharp.Core/local.fsi b/src/fsharp/FSharp.Core/local.fsi index 2b3ca276519..8c3f604096f 100644 --- a/src/fsharp/FSharp.Core/local.fsi +++ b/src/fsharp/FSharp.Core/local.fsi @@ -28,6 +28,8 @@ module internal List = val unzip : ('T1 * 'T2) list -> 'T1 list * 'T2 list val unzip3 : ('T1 * 'T2 * 'T3) list -> 'T1 list * 'T2 list * 'T3 list val windowed : int -> 'T list -> 'T list list + val chunkBySize : int -> 'T list -> 'T list list + val splitInto : int -> 'T list -> 'T list list val zip : 'T1 list -> 'T2 list -> ('T1 * 'T2) list val zip3 : 'T1 list -> 'T2 list -> 'T3 list -> ('T1 * 'T2 * 'T3) list val ofArray : 'T[] -> 'T list @@ -44,6 +46,8 @@ module internal Array = val inline init : int -> (int -> 'T) -> 'T[] + val splitInto : int -> 'T[] -> 'T[][] + val findBack: predicate:('T -> bool) -> array:'T[] -> 'T val tryFindBack: predicate:('T -> bool) -> array:'T[] -> 'T option diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index ffa109d2de4..fc297daebc2 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1828,3 +1828,29 @@ namespace Microsoft.FSharp.Collections while e.MoveNext() do let next = e.Current if (cached.Add next) then yield next } + + [] + let chunkBySize chunkSize (source : seq<_>) = + checkNonNull "source" source + if chunkSize <= 0 then invalidArg "chunkSize" (SR.GetString(SR.inputMustBePositive)) + seq { use e = source.GetEnumerator() + let nextChunk() = + let res = Array.zeroCreateUnchecked chunkSize + res.[0] <- e.Current + let i = ref 1 + while !i < chunkSize && e.MoveNext() do + res.[!i] <- e.Current + i := !i + 1 + if !i = chunkSize then + res + else + res |> Array.subUnchecked 0 !i + while e.MoveNext() do + yield nextChunk() } + + [] + let splitInto count source = + checkNonNull "source" source + if count <= 0 then invalidArg "count" (SR.GetString(SR.inputMustBePositive)) + mkDelayedSeq (fun () -> + source |> toArray |> Array.splitInto count :> seq<_>) diff --git a/src/fsharp/FSharp.Core/seq.fsi b/src/fsharp/FSharp.Core/seq.fsi index 3a64179219c..2dd5446ec86 100644 --- a/src/fsharp/FSharp.Core/seq.fsi +++ b/src/fsharp/FSharp.Core/seq.fsi @@ -129,6 +129,15 @@ namespace Microsoft.FSharp.Collections [] val choose: chooser:('T -> 'U option) -> source:seq<'T> -> seq<'U> + /// Divides the input sequence into chunks of size at most chunkSize. + /// The maximum size of each chunk. + /// The input sequence. + /// The sequence divided into chunks. + /// Thrown when the input sequence is null. + /// Thrown when chunkSize is not positive. + [] + val chunkBySize: chunkSize:int -> source:seq<'T> -> seq<'T[]> + /// Applies the given function to each element of the sequence and concatenates all the /// results. /// @@ -236,6 +245,17 @@ namespace Microsoft.FSharp.Collections [] val distinctBy: projection:('T -> 'Key) -> source:seq<'T> -> seq<'T> when 'Key : equality + /// Splits the input sequence into at most count chunks. + /// This function returns a sequence that digests the whole initial sequence as soon as that + /// sequence is iterated. As a result this function should not be used with large or infinite sequences. + /// The maximum number of chunks. + /// The input sequence. + /// The sequence split into chunks. + /// Thrown when the input sequence is null. + /// Thrown when count is not positive. + [] + val splitInto: count:int -> source:seq<'T> -> seq<'T[]> + /// Creates an empty sequence. /// /// An empty sequence.