2009-10-29 5 views
1

Existe-t-il un modèle d'instances multiples dans F # quelque part?Expression pour tester que tous les éléments dans la séquence sont les mêmes

Considérons que je travaille sur une liste. Je le schéma suivant correspondant

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? 

En d'autres termes qui passe [] ou [1] devrait renvoyer la liste et donc si [1, 1, 1, ...] mais je ne peux pas comprendre comment pour modéliser ce dernier motif. Est-ce possible? Ou y a-t-il une meilleure approche que je pourrais utiliser? Je n'ai rien trouvé à propos d'un répétant le motif.

Répondre

4

Je ne sais pas d'un modèle qui fait ce que vous voulez, mais vous pouvez le faire:

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

post-scriptum Vous parlez d'une séquence, mais votre correspondance indique que vous travaillez avec une liste. Le code correspondant à une séquence serait quelque chose comme

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

averti que la performance de cette fonction pourrait bien être pire que celle basée sur une liste.

+0

@cfern, vous avez raison. Je dois faire attention à la terminologie que j'utilise. J'ai tendance à utiliser "List" et "Sequence" comme s'ils étaient des synonymes - et en F # ils ne sont certainement pas synonymes. Je travaille avec une liste. –

0

Je considère une des manières suivantes:


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

ou


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

Il est toujours bon d'utiliser des fonctions de bibliothèque lorsque cela est possible;)

3

Voici une solution en utilisant plusieurs -case des modèles actifs.

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"