83 votes

Déterminer de façon élégante si plus d'un booléen est "vrai".

J'ai un ensemble de cinq valeurs booléennes. Si plus d'une de ces valeurs sont vraies, je veux exécuter une fonction particulière. Quel est le moyen le plus élégant auquel vous pensez pour me permettre de vérifier cette condition dans une seule instruction if() ? Le langage cible est le C# mais je suis également intéressé par des solutions dans d'autres langages (tant qu'il ne s'agit pas de fonctions intégrées spécifiques).

Une option intéressante consiste à stocker les booléens dans un octet, à effectuer un décalage vers la droite et à comparer avec l'octet d'origine. Quelque chose comme if(myByte && (myByte >> 1)) Mais cela nécessiterait de convertir les booléens séparés en octet (via un bitArray ?) et cela semble un peu (jeu de mots) maladroit... [edit]Sorry, that should have been if(myByte & (myByte - 1)) [/edit]

Note : Ceci est bien sûr très proche du problème de programmation classique de "comptage de population", "addition latérale" ou "poids de Hamming" - mais pas tout à fait le même. Je n'ai pas besoin de savoir combien de bits sont activés, seulement si c'est plus d'un. J'espère qu'il existe un moyen beaucoup plus simple d'accomplir cette tâche.

122voto

Daniel Earwicker Points 63298

J'allais écrire la version Linq, mais cinq personnes environ m'ont devancé. Mais j'aime vraiment l'approche des paramètres pour éviter d'avoir à créer manuellement un tableau. Donc je pense que le meilleur hybride est, basé sur la réponse de rp avec le corps remplacer avec l'évidence Linqness :

public static int Truth(params bool[] booleans)
{
    return booleans.Count(b => b);
}

Une clarté magnifique à lire et à utiliser :

if (Truth(m, n, o, p, q) > 2)

95voto

Charles Bretana Points 59899

Et si

  if ((bool1? 1:0) + (bool2? 1:0) + (bool3? 1:0) + 
      (bool4? 1:0) + (bool5? 1:0) > 1)
      // do something

ou une méthode généralisée serait...

   public bool ExceedsThreshold(int threshold, IEnumerable<bool> bools)
    {
       int trueCnt = 0;
       foreach(bool b in bools)
          if (b && (++trueCnt > threshold)) 
              return true;
       return false;          
    } 

ou en utilisant LINQ comme suggéré par d'autres réponses :

    public bool ExceedsThreshold(int threshold, IEnumerable<bool> bools)
    { return bools.Count(b => b) > threshold; }

EDIT (pour ajouter la suggestion de Joel Coehoorn : (dans .Net 2.x et plus)

    public void ExceedsThreshold<T>(int threshold, 
                      Action<T> action, T parameter, 
                      IEnumerable<bool> bools)
    { if (ExceedsThreshold(threshold, bools)) action(parameter); }

ou en .Net 3.5 et plus :

    public void ExceedsThreshold(int threshold, 
            Action action, IEnumerable<bool> bools)
    { if (ExceedsThreshold(threshold, bools)) action(); }

ou comme une extension de IEnumerable<bool>

  public static class IEnumerableExtensions
  {
      public static bool ExceedsThreshold<T> 
         (IEnumerable<bool> this bools, int threshold)
      { return bools.Count(b => b) > threshold; }
  }

l'usage serait alors :

  var bools = new [] {true, true, false, false, false, false, true};
  if (bools.ExceedsThreshold(3))
      // code to execute  ...

23voto

Garry Shutler Points 20898

C'est l'heure de la réponse obligatoire à la question LINQ, qui dans ce cas est en fait assez soignée.

var bools = new[] { true, true, false, false, false };

return bools.Count(b => b == true) > 1;

16voto

recursive Points 34729

Je les transformerais simplement en ints et en somme.

À moins que vous ne soyez dans une boucle interne super serrée, cela a l'avantage d'être facile à comprendre.

6voto

rp. Points 9997

J'écrirais une fonction qui recevrait un nombre quelconque de valeurs booléennes. Elle renverrait le nombre de ces valeurs qui sont vraies. Vérifiez le résultat pour le nombre de valeurs dont vous avez besoin d'être positif pour faire quelque chose.

Travaillez plus fort pour que ce soit clair, et non pas intelligent !

private int CountTrues( params bool[] booleans )
{
    int result = 0;
    foreach ( bool b in booleans )
    {
        if ( b ) result++;
    }

    return result;
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X