2010-11-10 15 views
9

Y at-il un chemin plus court de tester les éléments suivants:Comment puis-je tester si plusieurs booléens ont des valeurs identiques dans C#?

if (!((a == b) && (a == c) && (a == d) && (a == e) && (a == f))) 

J'ai fini par écrire une méthode qui me permet de le faire

if (!AllEqual(new[] { a, b, c, d, e, f })) 

qui se sent plus agréable et est beaucoup plus facile à lire, mais je Je me demande s'il y a quelque chose dans le cadre qui le fait déjà?

+2

Votre solution est la plus belle que je puisse penser au-dessus de ma tête. –

Répondre

13

Eh bien pour une chose, vous pouvez utiliser un tableau de paramètres pour le rendre plus simple:

public static bool AllEqual<T>(params T[] values) 
... 


if (AllEqual(a, b, c, d, e, f)) 
{ 
    ... 
} 

Je ne pense pas que vous trouverez rien de plus simple que cela, pour être honnête. Je n'ai vu cela nulle part ailleurs, ou dans le cadre. Eh bien, je suppose qu'il ya une chose que vous pourriez faire dans LINQ:

if (new { a, b, c, d, e, f }.Distinct().Count() == 1) 

Mais c'est assez horrible :)

Une version légèrement plus efficace de savoir:

if (!(new { a, b, c, d, e, f }).Distinct().Skip(1).Any())) 

.. qui retournera faux dès qu'il trouvera le second élément distinct. Avec seulement 6 éléments, je ne pense pas que ça vaut la peine de s'inquiéter si :)

+0

+1 Et je suggère également à OP de ne pas utiliser 6 variables bool, mais une 'bool []' à la place, ce qui est aussi plus facile à interroger avec '.Distinct'. –

+0

@Danny: Je pense que cela dépend du contexte - si les variables ont des significations très distinctes qui ont du sens, alors les garder séparées est logique. Si elles sont plus similaires - par ex. "est-ce que le champ 1 est rempli, le champ 2 est-il rempli" etc - alors un tableau serait en effet meilleur. –

+0

Merci pour l'idée du tableau param. Cela rend l'appel plus simple. –

0

Je ne pense pas que ce soit une bonne idée d'introduire une dépendance à un framework uniquement pour cela.

+3

Il a dit * le * framework - comme dans le framework .NET principal, j'imagine. –

+0

Désolé, vous avez raison. – Simone

0

Ce n'est pas quelque chose que les gens veulent généralement savoir. Vous pourriez facilement vérifier qu'ils étaient tous vrais en les associant et en les associant, ou qu'ils étaient tous faux en associant leurs non-croyants. Il est aussi très populaire en C++ de lancer des booléens et de les additionner - dans votre cas, vous cherchez un total de 6 ou de 0. Mais je pense que ces deux raisons obscurciraient votre raison d'être sachant que 6 drapeaux sont soit tout vrai ou tout faux.

1

Vous pouvez distribuer le! dans l'expression:

if ((a != b) || (a != c) || (a != d) || (a != e) || (a != f))) 

Vous pouvez également utiliser Any ou! All plutôt que d'ajouter une nouvelle méthode.

if (new[]{b, c, d, e, f}.Any(x => x != a)) ... 
2

Seulement si a, b, c, d, e et f sont des valeurs booléennes:

La façon la plus agréable est de jeter un oeil à Boolean logic et logic gates à simplify votre équation.

(Le == est comme un XNOR gate pour les valeurs booléennes)

Un exemple pour vous:

(!((a == b) && (a == c) && (a == d) && (a == e) && (a == f))) 

est le même que:

((a^b) || (a^c) || (a^d) || (a^e) || (a^f)) 

Mais je pense qu'il doit être intéressant faire à une revue de la logique qui vient à cela

[EDIT] En relation avec le Hightechrider's answers, la proposition

((a^b) || (a^c) || (a^d) || (a^e) || (a^f)) 

est équivalent à:

((a != b) || (a != c) || (a != d) || (a != e) || (a != f)) 

Mais Hightechrider's proposition fonctionner parfaitement, même si a, b, c, d, e et f ne sont pas booléens .

+0

Je visais la lisibilité. Bien que ce soit intéressant je ne suis pas sûr que je serai capable de le lire demain. –

+0

Je peux vous comprendre si vous n'êtes pas au courant de la logique booléenne: il m'a fallu du temps pour m'y habituer. cependant je pense qu'il est très important d'apprendre, même si dans ce cas la réponse de Jon Skeet semble être la meilleure solution, comparée à votre question ^^ –

+1

Évidemment, je suis d'accord que la forme complètement factorisée/simplifiée d'un booléen complexe L'expression est vraiment difficile à comprendre sans un commentaire rapide avec sa forme développée. –

1

Vous pouvez l'utiliser pour vérifier qu'ils sont tout à fait vrai:

if (a && b && c && d && e && f) { 
    ... 
} 

et cela pour vérifier qu'ils sont faux:

if (!(a || b || c || d || e || f)) { 
    ... 
} 

et vous pouvez combiner les deux pour vérifier qu'ils sont tous égaux:

if ((a && b && c && d && e && f) || !(a || b || c || d || e || f)) 
    ... 
} 

Mais très franchement, ce n'est pas mieux que votre solution originale :-)

Sur la base de ce qui précède, voici une mise en œuvre possible de AllEqual:

public static bool AllEqual(bool[] values) 
{ 
    bool andTerm = true; 
    bool orTerm = false; 
    foreach (bool v in values) 
    { 
     andResult &= v; 
     orResult |= v; 
    } 
    return andTerm || !orTerm; 
} 
+2

False: dans '(a && b && c && d && e && f)' si a, b, c, d, e et f sont 'true' , votre solution renvoie 'true', alors que' (! ((a == b) && (a == c) && (a == d) && (a == e) && (a == f)) ' retourne 'false', et'! (a || b || c || d || e || f) 'retourne' true' si a, b, c, d, e et f sont 'false' alors que' (! ((a == b) && (a == c) && (a == d) && (a == e) && (a == f))) 'return' false' ... Et le troisième toujours retourner 'true' quand a, b, c, d, e et f sont égaux, contrairement' (! ((a == b) && (a == c) && (a == d) && (a == e) && (a == f))) 'qui renvoie toujours' false' dans ce cas ... –

+0

@G. Qyy: Le titre de la question dit: "Comment puis-je tester que plusieurs booléens ont ** des valeurs identiques ** dans C#?". Les extraits de code dans la question utilisent en fait ceci pour tester que leurs valeurs ne sont pas ** égales à **, mais une fonction 'AllEqual' est ce que le PO demande explicitement. Ma réponse explique: 1) Comment tester pour tout vrai, 2) Comment tester pour tout faux, 3) Comment tester pour tous les égaux. Mon code fait ce que je dis. – Grodriguez

+0

Vous avez raison sur ce point: je comprends qu'il veut reproduire le comportement de son premier test, et je me soucie de quelques titres car ils exposent rarement toute la complexité de la question ... Bien sûr, votre code est bien comparé à ce que tu dis ça. mes excuses ^^ –

1

Utilisation BitArray:

gère une gamme compacte de valeurs de bits, qui sont représentés comme booléens, où vrai indique que le bit est sur (1) et faux indique que le bit est off (0).

// Your collection of bits 
bool a = false, b = false, c = false; 
// get them into an array 
bool[] d = new bool[] { a, b, c }; 
// intialize BitArray with that array 
System.Collections.BitArray e = new System.Collections.BitArray(d); 
// use OfType<>, Any<>, All<> 
if (Convert.ToBoolean(e.OfType<bool>().Any<bool>(condition => condition.Equals(true)) && e.OfType<bool>().Any<bool>(condition => condition.Equals(false)))) Console.WriteLine("some one is TRUE!."); 

Un exemple de code d'application console pour la démonstration:

class Program 
    { 
     static void Main(string[] args) 
     { 
      bool a = false, b = false, c = false; 
      bool[] d = new bool[] { a, b, c }; 
      System.Collections.BitArray e = new System.Collections.BitArray(d); 
      if (Convert.ToBoolean(e.OfType<bool>().Any<bool>(condition => condition.Equals(true)) && e.OfType<bool>().Any<bool>(condition => condition.Equals(false)))) Console.WriteLine("some one is TRUE!."); 
      if (Convert.ToBoolean(e.OfType<bool>().Any<bool>(condition => condition.Equals(true)) && e.OfType<bool>().Any<bool>(condition => condition.Equals(false)))) Console.WriteLine("some one is FALSE!."); 
      if (Convert.ToBoolean(e.OfType<bool>().All<bool>(condition => condition.Equals(true)))) Console.WriteLine("All of them are TRUE!."); 
      if (Convert.ToBoolean(e.OfType<bool>().All<bool>(condition => condition.Equals(false)))) Console.WriteLine("All of them are false!."); 
      Console.ReadLine(); 
     } 
    } 

MSDN Documentation surBitArray

1

Que diriez-vous ..

List<bool> arr = new List<bool>{ a, b, c, d, f }; 
bool allEqual = arr.TrueForAll(x => { return x; }) || arr.TrueForAll(x => { return !x; }); 

Looks assez élégant pour moi. :)