web-dev-qa-db-fra.com

Vérification de la liste des booléens si chaque élément de la liste est faux

J'ai un List<bool> avec beaucoup de valeurs. Quelle est la façon la plus efficace de vérifier si chaque élément de la liste est égal à false?

31
jacobz

Une solution beaucoup plus rapide, non mentionnée ici, utilise Contains

if (!myList.Contains(true))
    // Great success - all values false! 

J'ai comparé Contains contre IEnumerable.Any et Contains revient plus rapidement. Dans mes tests IEnumerable.All fait la même chose que IEnumerable.Any, un algorithme similaire est peut-être utilisé pour ces deux fonctions sous le capot. J'ai également vérifié IEnumerable.Exists qui a mieux performé que IEnumerable.Any et IEnumerable.All, mais était toujours plus lent que Contains.

Sur une liste de 10 000 000 d'entrées booléennes (j'ai aussi essayé 0 et 1 entrées, avec des résultats similaires), j'ai trouvé les métriques suivantes:

Écoulé via Tout = 95 ms

Écoulé via tous = 88 ms

Écoulé via Exists = 27 ms

Écoulé via contient = 17 ms

Contient est ~ 5.59x plus rapide que tout !

Testé avec le code suivant:

// setup initial vars
var myList = new List<bool>();
for (int x = 0; x < 10000000; x++)
    myList.Add(false);  

var containsAllFalse = false;
Stopwatch sw = new Stopwatch();

// start test
sw.Start();
containsAllFalse = !myList.Any(x => x);
sw.Stop();

// get result for Any
var timeAny = sw.ElapsedMilliseconds;

// reset variable state (just in case it affects anything)
containsAllFalse = false;   

// start test 2
sw.Restart();
containsAllFalse = myList.All(x => x == false);
sw.Stop();

// get result for All
var timeAll = sw.ElapsedMilliseconds;

// reset variable state (just in case it affects anything)
containsAllFalse = false;   

// start test 3
sw.Restart();
containsAllFalse = !myList.Exists(x => x == true);
sw.Stop();

// get result for All
var timeExists = sw.ElapsedMilliseconds;

// reset variable state (just in case it affects anything)
containsAllFalse = false;   

// start test 4
sw.Restart();   
containsAllFalse = !myList.Contains(true);          
sw.Stop();

// get result from Contains
var timeContains = sw.ElapsedMilliseconds;

// print results
var percentFaster = Math.Round((double)timeAny / timeContains, 2);
Console.WriteLine("Elapsed via Any = {0}ms", timeAny);
Console.WriteLine("Elapsed via All = {0}ms", timeAll);
Console.WriteLine("Elapsed via Exists = {0}ms", timeExists);
Console.WriteLine("Elapsed via Contains = {0}ms", timeContains);
Console.WriteLine("Contains is ~{0}x faster than Any!", percentFaster);


Notez que cela ne fonctionnera qu'avec des types où le type ne peut avoir que deux états (c'est-à-dire qu'il ne fonctionnera pas avec des variables de> 2 états, comme Nullable<bool>)

6
ChickenFeet

Vous pouvez utiliser Enumerable.Any il trouvera satisfaire la condition lors de la première correspondance. Comme Habib l'a dit à juste titre, il vaut mieux utiliser Any comme Enumerable.Tout retournerait vrai pour une liste vide de booléens.

!lst.Any(c=> c == true);

OU utilisez Enumerable.All

lst.All(c=> c == false);
36
Adil

Je suis d'accord avec l'utilisation de IEnumerable.Any / All . Cependant, je ne suis pas d'accord avec la réponse actuellement la plus votée (qui était erronée au moment de la rédaction de ce document) et plusieurs des commentaires associés de Any vs All.

Ces opérations suivantes sont équivalentes sémantiquement. Notez que les négations sont appliquées à la fois à l'intérieur, sur le prédicat et sur le résultat de l'opération.

!l.Any(x => f(x))
l.All(x => !f(x))

Maintenant, dans ce cas, nous recherchons donc:

Si ce n'est pas le cas où il y a une valeur vraie .

!l.Any(x => x)  // f(x) = x == true

Ou ,

Il est vrai que chaque valeur est pas vraie.

l.All(x => !x)  // f'(x) = !f(x) = !(x == true)

Il n'y a rien de spécial pour les listes vides, le résultat est le même: par ex. !empty.Any(..) est faux, tout comme empty.All(..) et la relation d'équivalence ci-dessus reste valide.

De plus, les deux formulaires sont évalués paresseusement et nécessitent le même nombre d'évaluations dans LINQ To Objects ; en interne, la différence, pour une implémentation de séquence, est simplement de nier la vérification du prédicat et de la valeur de résultat.

17
user2864740

Vous pouvez utiliser LINQ'sAll méthode:

list.All(x => x == false);

Cela renverra false immédiatement s'il trouve une valeur égale à true.

2
Selman Genç