I have a generic List
and I have to find a particular string in this list. Could you please let me know which is the best approach in the below?
if (strlist.开发者_如何学CContains("Test"))
{
// String found
}
or
string res = (from d in strlist where d == "Test" select d).SingleOrDefault();
if (res == "Test")
{
//found
}
Please consider the list may be very big populated from database. Your thoughts on this are highly appreciated.
If you have List<string>
(or even IEnumerable<string>
) and Contains meets your needs, then use Contains.
If you need some extra handling that Contains doesn't provide, I would suggest using Any():
if(strList.Any(s => s.StartsWith("Tes"))
{
// Found
}
The two methods will behave differently if there is more than one match; the first one will return true and the second one will throw an exception.
To correct that, change SingleOrDefault
to FirstOrDefault
.
To answer the question, you should call Contains
if you're searching for an exact match and Any
if you aren't.
For example:
if (strings.Contains("SomeString", StringComparer.OrdinalIgnoreCase))
if (strings.Any(s => s.StartsWith("b"))
You really should use HashSet<string>
as the the performance of Contains
is dramatically better. Now if you need to use a list for other operations you can simply have both available.
var list = BuildListOfStrings();
var set = new HashSet<string>(list);
if (set.Contains("Test"))
{
// ...
}
Now you have the ability to find items in the set as a O(1)
operation.
Test
static void Main(string[] args)
{
var lst = GenerateStrings().Take(5000000).ToList();
var hsh = new HashSet<string>(lst);
var found = false;
var count = 100;
var sw = Stopwatch.StartNew();
for (int i = 0; i < count; i++)
{
hsh = new HashSet<string>(lst);
}
Console.WriteLine(TimeSpan.FromTicks(sw.ElapsedTicks / count));
sw = Stopwatch.StartNew();
for (int i = 0; i < count; i++)
{
found = lst.Contains("12345678");
}
Console.WriteLine(TimeSpan.FromTicks(sw.ElapsedTicks / count));
sw = Stopwatch.StartNew();
for (int i = 0; i < count; i++)
{
found = hsh.Contains("12345678");
}
Console.WriteLine(TimeSpan.FromTicks(sw.ElapsedTicks / count));
Console.WriteLine(found);
Console.ReadLine();
}
private static IEnumerable<string> GenerateStrings()
{
var rnd = new Random();
while (true)
{
yield return rnd.Next().ToString();
}
}
Result
0.308438 s 0.0197868 s 0.0 s
So what does this tell us? If you are making a small amount of calls to Contains
use a List<string>
, otherwise use a HashSet<string>
.
精彩评论