Je voudrais tester si tous les éléments d'une liste / séquence sont égaux à quelque chose
Par exemple, une séquence d'entiers.
Je voudrais tester si TOUS les éléments de la séquence sont égaux à le même numéro.
Jusqu'à présent, ma solution ressemble à une solution de programmation impérative.
let test seq = if Seq.forall(fun num -> num =1) then 1 elif Seq.forall(fun num-> num = 2) then 2 else None
3 Réponses :
Vous pouvez le réécrire en utilisant une correspondance de modèle avec une clause de garde:
let testList = [2;2;2] let isOne x = x = 1 let isTwo x = x = 2 let forAll = function | list when list |> List.forall isOne -> Some 1 | list when list |> List.forall isTwo -> Some 2 | _ -> None let res = forAll testList //Some 2
Au lieu de la fonction, vous pouvez utiliser une application partielle sur l'opérateur égal.
> [1;2] |> List.pairwise |> List.forall (fun (a,b) -> a = b) ;; val it : bool = false > [1;1;1] |> List.pairwise |> List.forall (fun (a,b) -> a = b) ;; val it : bool = true
Cela semble peut-être plus fonctionnel? Et je pense que vous devriez retourner Some 1
dans votre code, sinon vous auriez des erreurs de type puisque Option et int ne sont pas du même type ...
Si vous voulez vérifier si tous les éléments sont égaux (pas seulement s'ils correspondent à une constante), vous pouvez faire ceci:
> let yes = [1;1;1];; val yes : int list = [1; 1; 1] > let no = [1;2;3];; val no : int list = [1; 2; 3] > yes |> List.forall ((=) 1);; val it : bool = true > no |> List.forall ((=) 1);; val it : bool = false
Là, vous divisez votre liste en tuples et vérifie si les tuples sont égaux. Cela signifie de manière transitoire que tous les éléments sont égaux.
Votre solution est bonne! Vérifier que tous les éléments d'une séquence ont une certaine valeur n'est pas quelque chose que vous pouvez bien exprimer en utilisant la correspondance de modèle - vous devez utiliser la clause when
, mais cela fait exactement la même chose que votre code (mais avec une syntaxe plus longue ). Dans des cas comme celui-ci, il n'y a absolument rien de mal à utiliser if
.
Vous pouvez étendre la correspondance de modèles en définissant des modèles actifs personnalisés, ce qui vous donne une option intéressante ici. C'est un F # assez avancé, mais vous pouvez définir un modèle personnalisé ForAll n
qui réussit lorsque l'entrée est une séquence contenant uniquement des valeurs n
:
let test = function | ForAll 1 -> Some 1 | ForAll 2 -> Some 2 | _ -> None
Notez que le succès est représenté par Certains
et l'échec par Aucun
. Maintenant, vous pouvez très bien résoudre votre problème en utilisant la correspondance de modèles:
let (|ForAll|_|) n seq = if Seq.forall (fun num -> num = n) seq then Some() else None
Cela a l'air plutôt sympa, mais cela s'appuie sur des fonctionnalités plus avancées - je le ferais si c'est quelque chose qui vous avez besoin de plus d'un endroit. Si j'avais besoin de cela juste à un seul endroit, j'irais avec if
ordinaire .