2009-10-29 22 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" 
相关问题