Ich machte eine Übung auf F# Wiki Book on List (scrollen Sie nach unten), um eine Pair
Methode zu erstellen.Wie erstellt man eine "Pair" -Funktion, die mit einer String-Liste übereinstimmt?
Ich konnte eine Integer-Liste ohne Probleme paaren, aber eine F # Ausnahme wurde für eine String-Liste geworfen. Es ist einfach zu kryptisch für mich zu entziffern, was die Ausnahme für einen F # Anfänger wie mich bedeutet.
Hier ist mein erster Versuch zur Umsetzung Pair
auf fsi.exe
> let pair l =
- let rec loop acc = function
- | [] -> acc
- | (hd1 :: hd2 :: tl) -> loop ((hd1, hd2) :: acc) tl
- List.rev(loop [] l)
-
- printfn "%A" ([1..10] |> pair)
- printfn "%A" ([ "one"; "two"; "three"; "four"; "five" ] |> pair);;
let rec loop acc = function
-----------------------^
stdin(2,24): warning FS0025: Incomplete pattern matches on this expression.
For example, the value '[_]' will not be matched
val pair : 'a list -> ('a * 'a) list
[(1, 2); (3, 4); (5, 6); (7, 8); (9, 10)]
Microsoft.FSharp.Core.MatchFailureException:
Exception of type 'Microsoft.FSharp.Core.MatchFailureException' was thrown.
at [email protected](List`1 acc, List`1 _arg1)
at FSI_0002.pair[T](List`1 l)
at <StartupCode$FSI_0002>.$FSI_0002._main()
stopped due to error
So Pair
funktioniert auf Integer-Version
und die Funktion Signatur
val pair : 'a list -> ('a * 'a) list
zeigt an, dass Pair
auf einer generischen Liste arbeitet.
Frage: Warum würde dann Pair
nicht auf einer String-Liste arbeiten?
[ANTWORT] (meine Version)
einfach angehäuft Liste Rückkehr für else
Fall (_) hat den Trick.
Und die Warnung ist auch erledigt.
let pair l =
let rec loop acc = function
// | [] -> acc
| (hd1 :: hd2 :: tl) -> loop ((hd1, hd2) :: acc) tl
| _ -> acc
List.rev(loop [] l)
printfn "%A" ([1..10] |> pair)
printfn "%A" ([ "one"; "two"; "three"; "four"; "five" ] |> pair)
[EDIT 2] Nun, ich werde auch meine Version von Unpair
auf Vollständigkeit stellen.
let unpair l = [for (a,b) in l do yield! a :: b :: []]
Hier ist etwas fehlerhaft Benchmarking, dass unter Verwendung von Lösungs Version gegen Mine für 1 Million Itemlisten
#light
open System;
let pn l = printfn "%A" l
let duration f =
let startTime = DateTime.Now;
let returnValue = f()
let endTime = DateTime.Now;
printfn "Duration (ms): %f" (endTime - startTime).TotalMilliseconds
returnValue
let ll = [for a in 1..1000000 do yield (a)]
let tl = [for a in 1..1000000 do yield (a,a)]
let pair1 l =
let rec loop acc = function
| [] | [_] -> List.rev acc
| h1 :: h2 :: tl -> loop ((h1, h2) :: acc) tl
loop [] l
let unpair1 l =
let rec loop acc = function
| [] -> List.rev acc
| (h1, h2) :: tl -> loop (h2 :: h1 :: acc) tl
loop [] l
let pair2 l =
let rec loop acc = function
| (hd1 :: hd2 :: tl) -> loop ((hd1, hd2) :: acc) tl
| _ | [_] -> acc
List.rev(loop [] l)
let unpair2 l = [for (a,b) in l do yield! a :: b :: []]
pn(duration (fun() -> ll |> pair1))
pn(duration (fun() -> tl |> unpair1))
pn(duration (fun() -> ll |> pair2))
pn(duration (fun() -> tl |> unpair2))
Benchmark Ergebnis:
Solution version
PAIR -> Duration (ms): 255.000000
UNPAIR -> Duration (ms): 840.000000
My version
PAIR -> Duration (ms): 220.000000
UNPAIR -> Duration (ms): 1624.000000
Übrigens, Wiki-Buch listet eine Lösung für die Umsetzung "Pair", aber ich entschied mich, nicht zu betrügen. – Sung