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

Implement Array.takeWhile, List.takeWhile

Commits:
    implementing "takeWhile" for array and list

    Check for ArgumentNullException in Array.takeWhile

    Performance optimization for Array.takeWhile

    Do not use array slicing in Array.takeWhile

    Use a temporary array for List.takeWhile

    Use mutable list version instead of temp array for List.takeWhile

    Adding surface area for takeWhile

    Adding more test cases for takeWhile

    Fix bug in List.takeWhile where predicate of first element is false

    Apply dsyme's suggestion on takeWhile
上级 3c39e6e2
......@@ -199,6 +199,19 @@ type ArrayModule() =
CheckThrowsInvalidOperationExn (fun () -> Array.take 5 [|"str1";"str2";"str3";"str4"|] |> ignore)
CheckThrowsArgumentNullException (fun () -> Array.take 5 null |> ignore)
[<Test>]
member this.takeWhile() =
Assert.AreEqual([||],Array.takeWhile (fun x -> failwith "should not be used") [||])
Assert.AreEqual([|1;2;4;5|],Array.takeWhile (fun x -> x < 6) [|1;2;4;5;6;7|])
Assert.AreEqual([|"a"; "ab"; "abc"|],Array.takeWhile (fun (x:string) -> x.Length < 4) [|"a"; "ab"; "abc"; "abcd"; "abcde"|])
Assert.AreEqual([|"a"; "ab"; "abc"; "abcd"; "abcde"|],Array.takeWhile (fun _ -> true) [|"a"; "ab"; "abc"; "abcd"; "abcde"|])
Assert.AreEqual([||],Array.takeWhile (fun _ -> false) [|"a"; "ab"; "abc"; "abcd"; "abcde"|])
Assert.AreEqual([||],Array.takeWhile (fun _ -> false) [|"a"|])
Assert.AreEqual([|"a"|],Array.takeWhile (fun _ -> true) [|"a"|])
Assert.AreEqual([|"a"|],Array.takeWhile (fun x -> x <> "ab") [|"a"; "ab"; "abc"; "abcd"; "abcde"|])
CheckThrowsArgumentNullException (fun () -> Array.takeWhile (fun _ -> failwith "should not be used") null |> ignore)
[<Test>]
member this.Blit() =
// int array
......
......@@ -180,7 +180,6 @@ type ListModule() =
let emptyChosen = List.choose funcInt emptySrc
Assert.AreEqual(emptySrc, emptyChosen)
()
[<Test>]
......@@ -203,6 +202,17 @@ type ListModule() =
Assert.AreEqual(0,List.compareWith (fun x y -> 0) ["1";"2"] ["1";"3"])
Assert.AreEqual(1,List.compareWith (fun x y -> 1) ["1";"2"] ["1";"3"])
Assert.AreEqual(-1,List.compareWith (fun x y -> -1) ["1";"2"] ["1";"3"])
[<Test>]
member this.takeWhile() =
Assert.AreEqual([],List.takeWhile (fun x -> failwith "should not be used") [])
Assert.AreEqual([1;2;4;5],List.takeWhile (fun x -> x < 6) [1;2;4;5;6;7])
Assert.AreEqual(["a"; "ab"; "abc"],List.takeWhile (fun (x:string) -> x.Length < 4) ["a"; "ab"; "abc"; "abcd"; "abcde"])
Assert.AreEqual(["a"; "ab"; "abc"; "abcd"; "abcde"],List.takeWhile (fun _ -> true) ["a"; "ab"; "abc"; "abcd"; "abcde"])
Assert.AreEqual([],List.takeWhile (fun _ -> false) ["a"; "ab"; "abc"; "abcd"; "abcde"])
Assert.AreEqual([],List.takeWhile (fun _ -> false) ["a"])
Assert.AreEqual(["a"],List.takeWhile (fun _ -> true) ["a"])
Assert.AreEqual(["a"],List.takeWhile (fun x -> x <> "ab") ["a"; "ab"; "abc"; "abcd"; "abcde"])
[<Test>]
member this.Concat() =
......
......@@ -163,6 +163,7 @@ Microsoft.FSharp.Collections.ArrayModule: T[] Singleton[T](T)
Microsoft.FSharp.Collections.ArrayModule: T[] SortBy[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], T[])
Microsoft.FSharp.Collections.ArrayModule: T[] SortWith[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,System.Int32]], T[])
Microsoft.FSharp.Collections.ArrayModule: T[] Sort[T](T[])
Microsoft.FSharp.Collections.ArrayModule: T[] TakeWhile[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], T[])
Microsoft.FSharp.Collections.ArrayModule: T[] Take[T](Int32, T[])
Microsoft.FSharp.Collections.ArrayModule: T[] Where[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], T[])
Microsoft.FSharp.Collections.ArrayModule: T[] ZeroCreate[T](Int32)
......@@ -306,6 +307,7 @@ Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList
Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[T] SortWith[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,System.Int32]], Microsoft.FSharp.Collections.FSharpList`1[T])
Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[T] Sort[T](Microsoft.FSharp.Collections.FSharpList`1[T])
Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[T] Tail[T](Microsoft.FSharp.Collections.FSharpList`1[T])
Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[T] TakeWhile[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.FSharpList`1[T])
Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[T] Take[T](Int32, Microsoft.FSharp.Collections.FSharpList`1[T])
Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[T] Where[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.FSharpList`1[T])
Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Core.FSharpOption`1[System.Int32] TryFindIndex[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.FSharpList`1[T])
......
......@@ -157,6 +157,7 @@ Microsoft.FSharp.Collections.ArrayModule: T[] Singleton[T](T)
Microsoft.FSharp.Collections.ArrayModule: T[] SortBy[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], T[])
Microsoft.FSharp.Collections.ArrayModule: T[] SortWith[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,System.Int32]], T[])
Microsoft.FSharp.Collections.ArrayModule: T[] Sort[T](T[])
Microsoft.FSharp.Collections.ArrayModule: T[] TakeWhile[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], T[])
Microsoft.FSharp.Collections.ArrayModule: T[] Take[T](Int32, T[])
Microsoft.FSharp.Collections.ArrayModule: T[] Where[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], T[])
Microsoft.FSharp.Collections.ArrayModule: T[] ZeroCreate[T](Int32)
......@@ -300,6 +301,7 @@ Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList
Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[T] SortWith[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,System.Int32]], Microsoft.FSharp.Collections.FSharpList`1[T])
Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[T] Sort[T](Microsoft.FSharp.Collections.FSharpList`1[T])
Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[T] Tail[T](Microsoft.FSharp.Collections.FSharpList`1[T])
Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[T] TakeWhile[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.FSharpList`1[T])
Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[T] Take[T](Int32, Microsoft.FSharp.Collections.FSharpList`1[T])
Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[T] Where[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.FSharpList`1[T])
Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Core.FSharpOption`1[System.Int32] TryFindIndex[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.FSharpList`1[T])
......
......@@ -120,6 +120,19 @@ namespace Microsoft.FSharp.Collections
Array.Copy(array, 0, res, 0, count)
res
[<CompiledName("TakeWhile")>]
let takeWhile predicate (array: 'T[]) =
checkNonNull "array" array
if array.Length = 0 then empty else
let mutable count = 0
while count < array.Length && predicate array.[count] do
count <- count + 1
let res : 'T[] = Microsoft.FSharp.Primitives.Basics.Array.zeroCreateUnchecked count
Array.Copy(array, 0, res, 0, count)
res
[<CompiledName("Append")>]
let append (array1:'T[]) (array2:'T[]) =
checkNonNull "array1" array1
......
......@@ -657,6 +657,18 @@ namespace Microsoft.FSharp.Collections
[<CompiledName("Take")>]
val take: count:int -> array:'T[] -> 'T[]
/// <summary>Returns an array that contains all elements of the original array while the
/// given predicate returns <c>true</c>, and then returns no further elements.</summary>
///
/// <param name="predicate">A function that evaluates to false when no more items should be returned.</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("TakeWhile")>]
val takeWhile: predicate:('T -> bool) -> array:'T[] -> 'T[]
/// <summary>Builds a list from the given array.</summary>
/// <param name="array">The input array.</param>
/// <returns>The list of array elements.</returns>
......
......@@ -90,6 +90,9 @@ namespace Microsoft.FSharp.Collections
[<CompiledName("Take")>]
let take count (list : 'T list) = Microsoft.FSharp.Primitives.Basics.List.take count list
[<CompiledName("TakeWhile")>]
let takeWhile p (list: 'T list) = Microsoft.FSharp.Primitives.Basics.List.takeWhile p list
[<CompiledName("IterateIndexed")>]
let iteri f list = Microsoft.FSharp.Primitives.Basics.List.iteri f list
......
......@@ -587,6 +587,16 @@ namespace Microsoft.FSharp.Collections
[<CompiledName("Take")>]
val take: count:int -> list:'T list -> 'T list
/// <summary>Returns a list that contains all elements of the original list while the
/// given predicate returns <c>true</c>, and then returns no further elements.</summary>
///
/// <param name="predicate">A function that evaluates to false when no more items should be returned.</param>
/// <param name="list">The input list.</param>
///
/// <returns>The result list.</returns>
[<CompiledName("TakeWhile")>]
val takeWhile: predicate:('T -> bool) -> list:'T list -> 'T list
/// <summary>Builds an array from the given list.</summary>
/// <param name="list">The input list.</param>
/// <returns>The array containing the elements of the list.</returns>
......
......@@ -466,6 +466,27 @@ module internal List =
res <- arr.[i] :: res
res
let rec takeWhileFreshConsTail cons p l =
match l with
| [] -> setFreshConsTail cons []
| x::xs ->
if p x then
let cons2 = freshConsNoTail x
setFreshConsTail cons cons2
takeWhileFreshConsTail cons2 p xs
else
setFreshConsTail cons []
let takeWhile p (l: 'T list) =
match l with
| [] -> l
| x :: ([] as nil) -> if p x then l else nil
| x::xs ->
if not (p x) then [] else
let cons = freshConsNoTail x
takeWhileFreshConsTail cons p xs
cons
// NOTE: This implementation is now only used for List.sortWith. We should change that to use the stable sort via arrays
// below, and remove this implementation.
module StableSortImplementation =
......
......@@ -28,6 +28,7 @@ module internal List =
val zip3 : 'T1 list -> 'T2 list -> 'T3 list -> ('T1 * 'T2 * 'T3) list
val ofArray : 'T[] -> 'T list
val take : int -> 'T list -> 'T list
val takeWhile : ('T -> bool) -> 'T list -> 'T list
val toArray : 'T list -> 'T[]
val sortWith : ('T -> 'T -> int) -> 'T list -> 'T list
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册