tags:

views:

73

answers:

4

Hi All

I have a generic List and i have to find a particular string in the list. Could you please let me know which is the best approach in the below ?

List<string> strlist = new List<string>();
//Add strings to List

if (strlist.Contains("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..

Regards

Balu

+4  A: 

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
}
Justin Niessner
Exacaly, compiler will make it's optimizations anyway and snippet with Contains looks much better ;)
ŁukaszW.pl
+2  A: 

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"))
SLaks
Actually the second will not. You are thinking `Single`.
ChaosPandion
@ChaosPandion: Wrong. `SingleOrDefault` will only return `default(T)` if there are _zero_ matches. Otherwise, it would be identical to `FirstOrDefault`.
SLaks
@SLaks - I know you really shouldn't read emotional intent from text but ouch.
ChaosPandion
@SLaks: SingleOrDefault will return the error if you return multiple rows rather than just one or none.
Jonathan Park
@Jonathan: That's what I meant.
SLaks
A: 

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>.

ChaosPandion
If he needs to preserve ordering, he shouldn't.
SLaks
@SLaks - Your obviously right but the fact that they mention that the list can be very large means that this will dramatically improve performance. Since `string` is a reference type they can simply keep a `List<string>` for other operations and not have to worry about excessive memory usage.
ChaosPandion
@ChaosP: That assumes that the contains of the list are fixed, and this task is performed repeatly. Building an ad hoc hashSet just to perform one Contain, will be slowing then just call Contains on a List,
James Curran
Wouldn't there be a performance hit of having to construct the HashSet to begin with?
rossisdead
@James, @rossisdead - See update.
ChaosPandion
A: 

Thanks guys! Excellent! I will use contains() as my requirement is very straight forwrd to check the occurence of a string..

Balu
Stack Overflow is **not** a discussion forum. Either add a comment to the answer(s) that helped - along with up-voting and/or accepting - or update your question.
ChrisF
You should accept an answer by clicking the hollow check.
SLaks