Coder Perfect

Case-Insensitive List Search


I have a testList list with a bunch of strings in it. I’d like to add a new string to the testList, but only if it doesn’t already exist. As a result, I need to make the list more efficient by performing a case-insensitive search. I’m unable to utilize Contains since it does not account for casing. For performance reasons, I also don’t want to use ToUpper/ToLower. This is a method I discovered that works:

    if(testList.FindAll(x => x.IndexOf(keyword, 
                       StringComparison.OrdinalIgnoreCase) >= 0).Count > 0)
       Console.WriteLine("Found in list");

This is effective, however it only matches incomplete words. If “goat” is already on the list, I can’t add “oat” since it says “oat” is already in the list. Is there a technique to effectively search lists without regard to case, where words must exactly match? thanks

Asked by Brap

Solution #1

I realise this is an old topic, but in case anyone else is interested, you can utilise Contains by specifying a case-insensitive string equality comparer as follows:

using System.Linq;

// ...

if (testList.Contains(keyword, StringComparer.OrdinalIgnoreCase))
    Console.WriteLine("Keyword Exists");

According to msdn, this has been accessible 2.0.

Answered by shaxby

Solution #2

If you want to avoid partial matches, use String.Equals instead of String.IndexOf. Also, instead of using FindAll, which goes through all of the elements, use FindIndex (it stops on the first one it hits).

if(testList.FindIndex(x => x.Equals(keyword,  
    StringComparison.OrdinalIgnoreCase) ) != -1) 
    Console.WriteLine("Found in list"); 

Use LINQ methods as an alternative (which also stops on the first one it hits)

if( testList.Any( s => s.Equals(keyword, StringComparison.OrdinalIgnoreCase) ) )
    Console.WriteLine("found in list");

Answered by Adam Sills

Solution #3

Here’s a great tidy extensions approach for Contains, based on Adam Sill’s answer above…:)

/// <summary>
/// Determines whether the specified list contains the matching string value
/// </summary>
/// <param name="list">The list.</param>
/// <param name="value">The value to match.</param>
/// <param name="ignoreCase">if set to <c>true</c> the case is ignored.</param>
/// <returns>
///   <c>true</c> if the specified list contais the matching string; otherwise, <c>false</c>.
/// </returns>
public static bool Contains(this List<string> list, string value, bool ignoreCase = false)
    return ignoreCase ?
        list.Any(s => s.Equals(value, StringComparison.OrdinalIgnoreCase)) :

Answered by Lance Larsen – Microsoft MVP

Solution #4

StringComparer static variations can be used with the LINQ Contains overload, for example:

using System.Linq;

var list = new List<string>();

if (list.Contains("MOTH", StringComparer.OrdinalIgnoreCase))

Answered by jlo-gmail

Solution #5

Here’s an extension method with the recommended string, based on Lance Larsen’s response. Instead of string, use compare. Equals

public static bool Contains(this List<string> source, string toCheck, StringComparison comp)
       source != null &&
       !string.IsNullOrEmpty(toCheck) &&
       source.Any(x => string.Compare(x, toCheck, comp) == 0);

Answered by dontbyteme

Post is based on