1
votes

F #: Comment tester l'égalité des éléments de séquence / liste?

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

f#

0 commentaires

3 Réponses :


3
votes

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


0 commentaires

3
votes

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.


0 commentaires

5
votes

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 .


0 commentaires