2009-10-29 62 views
1

F#中是否有多個實例模式?表達式測試順序中的所有項都是相同的

想想我正在做一個清單。我有以下模式匹配

match l with 
| [] | [_] -> l //if the list is empty or contains only one item, simply return it 
|   

    //is there a pattern to test if all of the elements are identical? 

換句話說通過[]或[1]應該簡單地返回列表等應當[1; 1; 1; ...]但我無法弄清楚如何模式匹配最後的模式。這可能嗎?或者有更好的方法可以使用?我還沒有找到任何關於重複模式的任何地方。

回答

4

我不知道你想要做什麼的任何圖案的,但你可以這樣做:

let allSame L = 
    match L with 
    | [] | [_] -> L 
    | h::t when t |> List.forall ((=) h) -> L 
    | _ -> failwith "unpossible!" //handle the failing match here 

附:你在談論一個序列,但你的匹配表明你正在使用一個列表。一個序列對應的代碼會是這樣的

let allSameSeq s = 
    match Seq.length s with 
    | 0 | 1 -> s 
    | _ when Seq.skip 1 s |> Seq.forall ((=) (Seq.head s)) -> s 
    | _ -> failwith "unpossible!" 

被警告說,這個功能的性能可能比基於列表的一個更糟糕。

+0

@cfern,你說得對。我確實需要小心使用的術語。我傾向於使用「列表」和「序列」,就好像它們是同義詞 - 而在F#中它們絕對不是同義詞。我正在處理一個清單。 – 2009-10-29 12:00:42

0

我會考慮做以下之一:


yourSequence |> Seq.windowed(2) |> Seq.forall(fun arr -> arr.[0] = arr.[1]) 


let h = Seq.hd yourSequence 
yourSequence |> Seq.forall((=) h) 

它總是好的可能時使用的庫函數;)

3

下面是使用多的解決方案 - 活動模式。

let (|SingleOrEmpty|AllIdentical|Neither|) (lst:'a list) = 
    if lst.Length < 2 then 
     SingleOrEmpty 
    elif List.forall (fun elem -> elem = lst.[0]) lst then 
     AllIdentical 
    else 
     Neither 

let allElementsIdentical lst:'a list = 
    match lst with 
    |SingleOrEmpty|AllIdentical -> lst 
    |Neither -> failwith "Not a suitable list"