En C # si j'ai une liste de type bool. Quel est le moyen le plus rapide de déterminer si la liste contient une valeur vraie? Je n'ai pas besoin de savoir combien ou où se trouve la vraie valeur. J'ai juste besoin de savoir s'il en existe un. Je vais chercher beaucoup de listes extrêmement volumineuses.
Utilisez list.Contains (true) ou list.Any (true) . Pour une liste normale, la complexité est O (n). Étant donné que Any () est une méthode d’extension nécessitant l’appel de délégués, la méthode Contains () est peut-être encore un peu plus rapide. Mais pour être sûr, je voudrais simplement tester les deux avec une grande collection.
Utilisez simplement bool trueInList = list.Contains(true);
. Cela boucle la liste jusqu'à ce qu'il y ait une true
.
Pourquoi avez-vous besoin de quelque chose de plus rapide avec un cas d'utilisation aussi simple?
Vous pouvez utiliser Any ().
list.Any(b => b);
Essaye ça:
var result = myBoolList.Any(i => i==true);
Ce sera le moyen le plus rapide:
static bool AnySet(List<bool> data)
{
for (int i = 0; i < data.Count; ++i)
if (data[i])
return true;
return false;
}
Méfiez-vous des réponses impliquant Linq. Ils seront plus lents, comme le montre ce programme de test (en fait, le Linq est plus de 12 fois plus lent!
Cela démontre également que (sur mon système au moins) la boucle codée à la main est environ 3,5 fois plus rapide que List.Contains()
.
Résultats sur mon PC (Windows 8 x64, programme compilé en x86)
Times in seconds
01.0994496 data.Any() list
01.1147795 data.Any() enumerable
00.1215951 hand-rolled loop
00.4240996 list.Contains()
J'ai testé cela sur plusieurs systèmes, y compris un ordinateur portable de 5 ans sous XP et un nouveau PC sous Windows 8, avec des résultats similaires.
(N'oubliez pas de faire vos timings à partir d'une version RELEASE.)
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
namespace ConsoleApplication1
{
internal class Program
{
private static void Main(string[] args)
{
int size = 10000000;
int count = 10;
List<bool> data = new List<bool>(size);
for (int i = 0; i < size; ++i)
data.Add(false);
var sw = Stopwatch.StartNew();
for (int trial = 0; trial < 5; ++trial)
{
sw.Restart();
for (int i = 0; i < count; ++i)
AnySet1(data);
Console.WriteLine(sw.Elapsed + " data.Any() list");
sw.Restart();
for (int i = 0; i < count; ++i)
AnySet2(data);
Console.WriteLine(sw.Elapsed + " data.Any() enumerable");
sw.Restart();
for (int i = 0; i < count; ++i)
AnySet3(data);
Console.WriteLine(sw.Elapsed + " hand-rolled loop");
sw.Restart();
for (int i = 0; i < count; ++i)
AnySet4(data);
Console.WriteLine(sw.Elapsed + " list.Contains()");
Console.WriteLine();
}
}
static bool AnySet1(List<bool> data)
{
return data.Any(b => b);
}
static bool AnySet2(IEnumerable<bool> data)
{
return data.Any(b => b);
}
static bool AnySet3(List<bool> data)
{
for (int i = 0; i < data.Count; ++i)
if (data[i])
return true;
return false;
}
static bool AnySet4(List<bool> data)
{
return data.Contains(true);
}
}
}
Alors, pourquoi diable List.Contains()
serait-il plus lent? Eh bien, utilisons réflecteur pour regarder sa mise en œuvre:
bool Contains(T item)
{
if (item == null)
{
for (int j = 0x0; j < this._size; j++)
{
if (this._items[j] == null)
{
return true;
}
}
return false;
}
EqualityComparer<T> comparer = EqualityComparer<T>.Default;
for (int i = 0x0; i < this._size; i++)
{
if (comparer.Equals(this._items[i], item))
{
return true;
}
}
return false;
}
Aha! Tout est révélé! Il appelle comparer.Equals()
pour chaque élément. Pas étonnant que ce soit plus lent!
Deux autres choses que je voudrais mentionner:
BitArray
dans laquelle vous stockez les bits bools sous forme de bits dans des entiers non signés 32 bits. Ensuite, vous pouvez vraiment zoomer en vérifiant 32 bits à la fois avec un simple != 0
sur chaque uint.Vous utilisez le Any(...)
list.Any(c => c == true);
ou juste
list.Any(c => c);
Cette réponse fournit un angle différent sur ceci: Pourquoi stocker les bools dans une liste? Stockez-les sous deux ints: int falseCount; int trueCount;
.
Contains-testing est aussi simple que: trueCount > 0
En supposant que vous ayez besoin de la liste, utilisez List.Contains
car il recherche directement le tableau sous-jacent.
Il serait encore plus rapide d'extraire le tableau sous-jacent à l'aide de la réflexion et de le rechercher dans une boucle de comparaison codée en dur. Vous pouvez utiliser la valeur true
littérale pour comparer chaque élément. Vous pouvez même dérouler la boucle ou faire des tours de code non sécurisés.
bool val = false;
Foreach(bool val in listofvalue)
{
val |= val;
}
if(val)
print "List contain true value"
else
print "List contain false value"
Vous pouvez utiliser la méthode BinarySearch de la liste.
if(list.BinarySearch(true) > 0){...}