提交 321dcde0 编写于 作者: S Steffen Forkmann 提交者: latkin

Implement Array.countBy, List.countBy

commit 30c0a3284b42ec0fd59bd57d8a63f63613b77301
Author: latkin <latkin@microsoft.com>
Date:   Sun Oct 12 12:35:13 2014 -0700

    Changing List.countBy to dedicated implementation

commit 976c6e995bdad2ac55ec8314aa1d03c66f644423
Merge: 15f04de4 c521808
Author: latkin <latkin@microsoft.com>
Date:   Sun Oct 12 10:43:21 2014 -0700

    Merge branch 'countBy3' of https://git01.codeplex.com/forks/forki/fsharp into PR

    Conflicts:
    	src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Collections/ListModule.fs
    	src/fsharp/FSharp.Core/seq.fsi

commit c5218084e04c4fb9ea5a1ee6c92c8647258cb542
Author: Steffen Forkmann <steffen.forkmann@msu-solutions.de>
Date:   Sat Jul 5 10:47:27 2014 +0200

    ok variable is not needed in countBy

commit fa934cf2aa536662df38175388d94665c7d87132
Author: Steffen Forkmann <steffen.forkmann@msu-solutions.de>
Date:   Fri Jul 4 15:36:20 2014 +0200

    Adding surface area for countBy

commit 63e669155017bf186bfdeb7db47a2f59bdce6765
Author: Steffen Forkmann <steffen.forkmann@msu-solutions.de>
Date:   Wed Jul 2 16:59:46 2014 +0200

    Use direct array implementation for Array.countBy

commit 0a975603f071973a19a10f1cb4c4cedc78d05158
Author: Steffen Forkmann <steffen.forkmann@msu-solutions.de>
Date:   Wed Jul 2 16:34:50 2014 +0200

    Use only one test method for countBy

commit a25a085cab89b1a9af193e19f8469e25a984f0bf
Author: Steffen Forkmann <steffen.forkmann@msu-solutions.de>
Date:   Wed Jul 2 16:32:51 2014 +0200

    Fix typo in countBy docs

commit 5d9af6ea78000d5aab885f6361556a72a6d04078
Author: Steffen Forkmann <steffen.forkmann@msu-solutions.de>
Date:   Wed Jul 2 16:32:40 2014 +0200

    Rename to array in Array.countBy

commit deeaba955ce60ef3981797d16ec423a1f34f863a
Author: Steffen Forkmann <steffen.forkmann@msu-solutions.de>
Date:   Mon Jun 30 16:15:02 2014 +0200

    Show possible System.ArgumentNullException in docs for Array.countBy

commit 532cdccafd47561517e276acc98b990e5f78b6f1
Author: Steffen Forkmann <steffen.forkmann@msu-solutions.de>
Date:   Mon Jun 30 12:10:39 2014 +0200

    implementing "countBy" for array and list
上级 15f04de4
......@@ -421,7 +421,18 @@ type ArrayModule() =
CheckThrowsNullRefException (fun () -> Array.concat nullArrays |> ignore)
()
[<Test>]
member this.countBy() =
// countBy should work on empty array
Assert.AreEqual([],Array.countBy (fun _ -> failwith "should not be executed") [||])
// countBy should not work on null
CheckThrowsArgumentNullException(fun () -> Array.countBy (fun _ -> failwith "should not be executed") null |> ignore)
// countBy should count by the given key function
Assert.AreEqual([| 5,1; 2,2; 3,2 |],Array.countBy id [|5;2;2;3;3|])
Assert.AreEqual([| 3,3; 2,2; 1,3 |],Array.countBy (fun x -> if x < 3 then x else 3) [|5;2;1;2;3;3;1;1|])
[<Test>]
member this.Copy() =
......
......@@ -263,6 +263,16 @@ type ListModule() =
CheckThrowsInvalidOperationExn (fun () -> List.splitAt 1 [] |> ignore)
CheckThrowsArgumentException (fun () -> List.splitAt -1 [0;1] |> ignore)
CheckThrowsInvalidOperationExn (fun () -> List.splitAt 5 ["str1";"str2";"str3";"str4"] |> ignore)
()
[<Test>]
member this.countBy() =
// countBy should work on empty list
Assert.AreEqual([],List.countBy (fun _ -> failwith "should not be executed") [])
// countBy should count by the given key function
Assert.AreEqual([5,1; 2,2; 3,2],List.countBy id [5;2;2;3;3])
Assert.AreEqual([3,3; 2,2; 1,3],List.countBy (fun x -> if x < 3 then x else 3) [5;2;1;2;3;3;1;1])
[<Test>]
member this.Exists() =
......
......@@ -115,6 +115,7 @@ Microsoft.FSharp.Collections.ArrayModule: System.String ToString()
Microsoft.FSharp.Collections.ArrayModule: System.Tuple`2[T,T][] Pairwise[T](T[])
Microsoft.FSharp.Collections.ArrayModule: System.Tuple`2[T1,T2][] Zip[T1,T2](T1[], T2[])
Microsoft.FSharp.Collections.ArrayModule: System.Tuple`2[T1[],T2[]] Unzip[T1,T2](System.Tuple`2[T1,T2][])
Microsoft.FSharp.Collections.ArrayModule: System.Tuple`2[TKey,System.Int32][] CountBy[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], T[])
Microsoft.FSharp.Collections.ArrayModule: System.Tuple`2[T[],T[]] Partition[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], T[])
Microsoft.FSharp.Collections.ArrayModule: System.Tuple`2[T[],T[]] SplitAt[T](Int32, T[])
Microsoft.FSharp.Collections.ArrayModule: System.Tuple`3[T1,T2,T3][] Zip3[T1,T2,T3](T1[], T2[], T3[])
......@@ -284,6 +285,7 @@ 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[System.Tuple`2[T,T]] Pairwise[T](Microsoft.FSharp.Collections.FSharpList`1[T])
Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`2[T1,T2]] Zip[T1,T2](Microsoft.FSharp.Collections.FSharpList`1[T1], Microsoft.FSharp.Collections.FSharpList`1[T2])
Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`2[TKey,System.Int32]] CountBy[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], Microsoft.FSharp.Collections.FSharpList`1[T])
Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`3[T1,T2,T3]] Zip3[T1,T2,T3](Microsoft.FSharp.Collections.FSharpList`1[T1], Microsoft.FSharp.Collections.FSharpList`1[T2], Microsoft.FSharp.Collections.FSharpList`1[T3])
Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[TResult] Choose[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpOption`1[TResult]], Microsoft.FSharp.Collections.FSharpList`1[T])
Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[TResult] Collect[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Collections.FSharpList`1[TResult]], Microsoft.FSharp.Collections.FSharpList`1[T])
......
......@@ -109,6 +109,7 @@ Microsoft.FSharp.Collections.ArrayModule: System.String ToString()
Microsoft.FSharp.Collections.ArrayModule: System.Tuple`2[T,T][] Pairwise[T](T[])
Microsoft.FSharp.Collections.ArrayModule: System.Tuple`2[T1,T2][] Zip[T1,T2](T1[], T2[])
Microsoft.FSharp.Collections.ArrayModule: System.Tuple`2[T1[],T2[]] Unzip[T1,T2](System.Tuple`2[T1,T2][])
Microsoft.FSharp.Collections.ArrayModule: System.Tuple`2[TKey,System.Int32][] CountBy[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], T[])
Microsoft.FSharp.Collections.ArrayModule: System.Tuple`2[T[],T[]] Partition[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], T[])
Microsoft.FSharp.Collections.ArrayModule: System.Tuple`2[T[],T[]] SplitAt[T](Int32, T[])
Microsoft.FSharp.Collections.ArrayModule: System.Tuple`3[T1,T2,T3][] Zip3[T1,T2,T3](T1[], T2[], T3[])
......@@ -278,6 +279,7 @@ 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[System.Tuple`2[T,T]] Pairwise[T](Microsoft.FSharp.Collections.FSharpList`1[T])
Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`2[T1,T2]] Zip[T1,T2](Microsoft.FSharp.Collections.FSharpList`1[T1], Microsoft.FSharp.Collections.FSharpList`1[T2])
Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`2[TKey,System.Int32]] CountBy[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], Microsoft.FSharp.Collections.FSharpList`1[T])
Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`3[T1,T2,T3]] Zip3[T1,T2,T3](Microsoft.FSharp.Collections.FSharpList`1[T1], Microsoft.FSharp.Collections.FSharpList`1[T2], Microsoft.FSharp.Collections.FSharpList`1[T3])
Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[TResult] Choose[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpOption`1[TResult]], Microsoft.FSharp.Collections.FSharpList`1[T])
Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[TResult] Collect[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Collections.FSharpList`1[TResult]], Microsoft.FSharp.Collections.FSharpList`1[T])
......
......@@ -168,6 +168,24 @@ namespace Microsoft.FSharp.Collections
Array.Copy(array, 0, res, 0, count)
res
[<CompiledName("CountBy")>]
let countBy projection (array:'T[]) =
checkNonNull "array" array
let dict = new Dictionary<Microsoft.FSharp.Core.CompilerServices.RuntimeHelpers.StructBox<'Key>,int>(Microsoft.FSharp.Core.CompilerServices.RuntimeHelpers.StructBox<'Key>.Comparer)
// Build the groupings
for v in array do
let key = Microsoft.FSharp.Core.CompilerServices.RuntimeHelpers.StructBox (projection v)
let mutable prev = Unchecked.defaultof<_>
if dict.TryGetValue(key, &prev) then dict.[key] <- prev + 1 else dict.[key] <- 1
let res = Microsoft.FSharp.Primitives.Basics.Array.zeroCreateUnchecked dict.Count
let mutable i = 0
for group in dict do
res.[i] <- group.Key.Value, group.Value
i <- i + 1
res
[<CompiledName("Append")>]
let append (array1:'T[]) (array2:'T[]) =
checkNonNull "array1" array1
......
......@@ -94,6 +94,19 @@ namespace Microsoft.FSharp.Collections
[<CompiledName("Copy")>]
val copy: array:'T[] -> 'T[]
/// <summary>Applies a key-generating function to each element of an array and returns an array yielding unique
/// keys and their number of occurrences in the original array.</summary>
///
/// <param name="projection">A function transforming each item of the input array into a key to be
/// compared against the others.</param>
/// <param name="array">The input array.</param>
///
/// <returns>The result array.</returns>
///
/// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
[<CompiledName("CountBy")>]
val countBy : projection:('T -> 'Key) -> array:'T[] -> ('Key * int)[] when 'Key : equality
/// <summary>Creates an array whose elements are all initially the given value.</summary>
/// <param name="count">The length of the array to create.</param>
/// <param name="value">The value for the elements.</param>
......
......@@ -32,6 +32,23 @@ namespace Microsoft.FSharp.Collections
[<CompiledName("Concat")>]
let concat lists = Microsoft.FSharp.Primitives.Basics.List.concat lists
[<CompiledName("CountBy")>]
let countBy projection (list:'T list) =
let dict = new Dictionary<Microsoft.FSharp.Core.CompilerServices.RuntimeHelpers.StructBox<'Key>,int>(Microsoft.FSharp.Core.CompilerServices.RuntimeHelpers.StructBox<'Key>.Comparer)
let rec loop srcList =
match srcList with
| [] -> ()
| h::t ->
let key = Microsoft.FSharp.Core.CompilerServices.RuntimeHelpers.StructBox (projection h)
let mutable prev = 0
if dict.TryGetValue(key, &prev) then dict.[key] <- prev + 1 else dict.[key] <- 1
loop t
loop list
let mutable result = []
for group in dict do
result <- (group.Key.Value, group.Value) :: result
result |> rev
[<CompiledName("Map")>]
let map f list = Microsoft.FSharp.Primitives.Basics.List.map f list
......
......@@ -109,6 +109,17 @@ namespace Microsoft.FSharp.Collections
[<CompiledName("DistinctBy")>]
val distinctBy: projection:('T -> 'Key) -> list:'T list -> 'T list when 'Key : equality
/// <summary>Applies a key-generating function to each element of a list and returns a list yielding unique
/// keys and their number of occurrences in the original list.</summary>
///
/// <param name="projection">A function transforming each item of the input list into a key to be
/// compared against the others.</param>
/// <param name="list">The input list.</param>
///
/// <returns>The result list.</returns>
[<CompiledName("CountBy")>]
val countBy : projection:('T -> 'Key) -> list:'T list -> ('Key * int) list when 'Key : equality
/// <summary>Returns an empty list of the given type.</summary>
[<GeneralizableValue>]
[<CompiledName("Empty")>]
......
......@@ -1369,9 +1369,7 @@ namespace Microsoft.FSharp.Collections
source |> iter (fun v ->
let key = StructBox (keyf v )
let mutable prev = Unchecked.defaultof<_>
let ok = dict.TryGetValue(key, &prev)
if ok then dict.[key] <- prev + 1
else dict.[key] <- 1)
if dict.TryGetValue(key, &prev) then dict.[key] <- prev + 1 else dict.[key] <- 1)
dict |> map (fun group -> (group.Key.Value, group.Value)))
......
......@@ -183,7 +183,7 @@ namespace Microsoft.FSharp.Collections
[<CompiledName("Contains")>]
val inline contains: value:'T -> source:seq<'T> -> bool when 'T : equality
/// <summary>Applies a key-generating function to each element of a sequence and return a sequence yielding unique
/// <summary>Applies a key-generating function to each element of a sequence and returns a sequence yielding unique
/// keys and their number of occurrences in the original sequence.</summary>
///
/// <remarks>Note that this function returns a sequence that digests the whole initial sequence as soon as
......@@ -191,7 +191,7 @@ namespace Microsoft.FSharp.Collections
/// large or infinite sequences. The function makes no assumption on the ordering of the original
/// sequence.</remarks>
///
/// <param name="projection">A function transforming each item of input sequence into a key to be
/// <param name="projection">A function transforming each item of the input sequence into a key to be
/// compared against the others.</param>
/// <param name="source">The input sequence.</param>
///
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册