2009-04-26 72 views
1

我在做F# Wiki Book on List的練習(滾動到底部)創建一個Pair方法。如何創建一個「Pair」函數來匹配字符串列表?

我能夠毫無問題地配對整數列表,但是爲字符串列表拋出了F#異常。對於我來說,對於像我這樣的F#初學者來說,破解這個例外意味着太神祕了。

這是我初次嘗試實施Pairfsi.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 

所以Pair不整數版本
工作和函數簽名

val pair : 'a list -> ('a * 'a) list 

表示Pair泛型列表上運行。

問題:那麼爲什麼Pair不能在字符串列表上工作?

【答案】(我的版本)
簡單地返回累積列表else情況下(_)的伎倆。
並且警告也被照顧。

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) 

[EDIT2]嗯,我也將張貼我的版本的Unpair的完整性。

let unpair l = [for (a,b) in l do yield! a :: b :: []] 

下面是使用的解決方案版本,針對我的有點瑕疵基準100萬個項目列表

#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)) 

基準測試結果:

Solution version 
PAIR -> Duration (ms): 255.000000 
UNPAIR -> Duration (ms): 840.000000 

My version 
PAIR -> Duration (ms): 220.000000 
UNPAIR -> Duration (ms): 1624.000000 
+0

順便說一句,維基書籍列出了實施「配對」的解決方案,但我決定不作弊。 – Sung 2009-04-26 23:45:09

回答

6

我不認爲你的版本Pair可以在任何奇數的列表上工作。你碰巧測試了偶數個數和奇數個字符串。我認爲你的第二個匹配參數意味着至少有兩個成員的列表。所以你中斷了2次中斷,並獲得了1個元素的列表,並且你的條件都不匹配。

[_]是一個包含任何內容的項目列表。您必須提供與其匹配的謂詞。

+0

我剛剛返回任何累計值返回「其他」的情況。有用!謝謝 - 答案張貼在問題中。 – Sung 2009-04-27 00:26:32

相關問題