如果我有一个bool类型的列表,请在C#中。确定列表是否包含真值的最快方法是什么?我不需要知道真正价值的数量或位置。我只需知道一个是否存在。我将搜索许多非常大的列表。
答案 0 :(得分:20)
只需使用bool trueInList = list.Contains(true);
即可。这将循环列表,直到有true
。
为什么在这么简单的用例中你需要更快的东西?
答案 1 :(得分:7)
使用list.Contains(true)或list.Any(true)。 对于正常列表,两者都具有复杂度O(n)。由于Any()是一种扩展方法,需要调用委托,所以Contains()可能会更快一些。但是要确保我只是用大量的集合来测试它们。
答案 2 :(得分:5)
您可以使用Any()。
list.Any(b => b);
答案 3 :(得分:3)
试试这个:
var result = myBoolList.Any(i => i==true);
答案 4 :(得分:2)
这将是最快的方式:
static bool AnySet(List<bool> data)
{
for (int i = 0; i < data.Count; ++i)
if (data[i])
return true;
return false;
}
小心涉及Linq的答案。它们会慢一点,正如这个测试程序所展示的那样(事实上,Linq的速度要快12倍!
这也表明(至少在我的系统上)手动编码循环比List.Contains()
快3.5倍。
我的电脑上的结果(Windows 8 x64,程序编译为x86)
Times in seconds
01.0994496 data.Any() list
01.1147795 data.Any() enumerable
00.1215951 hand-rolled loop
00.4240996 list.Contains()
我在几个系统上测试了这个,包括一台运行XP的5年旧笔记本电脑和一台装有Windows 8的新电脑,结果相似。
(不要忘记从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);
}
}
}
那么,为什么List.Contains()
会慢一些呢?好吧,让我们用反射器来看看它的实现:
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;
}
啊哈!一切都揭晓了!它为每个元素调用comparer.Equals()
。难怪它慢一点!
我还想提两件事:
BitArray
版本,将bools存储为32位无符号整数的位。然后你可以真正地缩放它,每次检查32位,每个uint上只有一个简单的!= 0
。答案 5 :(得分:1)
您使用Any(...)
list.Any(c => c == true);
或只是
list.Any(c => c);
答案 6 :(得分:1)
这个答案提供了一个不同的角度:为什么将bool存储在列表中?将它们存储为两个整数:int falseCount; int trueCount;
。
包含测试非常简单:trueCount > 0
假设您需要列表,请使用List.Contains
,因为它直接搜索基础数组。
使用反射提取底层数组并在硬编码比较循环中搜索它会更快。您可以使用文字true
来比较每个元素。你甚至可以展开循环或做不安全的代码技巧。
答案 7 :(得分:0)
bool val = false;
Foreach(bool val in listofvalue)
{
val |= val;
}
if(val)
print "List contain true value"
else
print "List contain false value"
答案 8 :(得分:0)
您可以使用列表中的BinarySearch方法。
if(list.BinarySearch(true) > 0){...}