关于C#:不区分大小写的列表搜索

Case-Insensitive List Search

我有一个列表testList,其中包含一系列字符串。我想在testList中添加一个新的字符串,前提是它不在列表中。因此,我需要对列表进行不区分大小写的搜索,并使其高效。我不能使用Contains,因为这不考虑外壳。出于性能原因,我也不想使用ToUpper/ToLower。我遇到了这个方法,它可以工作:

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

这是可行的,但它也匹配部分单词。如果列表中包含"goat",我就不能添加"oat",因为它声称"oat"已经在列表中。有没有一种方法可以有效地以不区分大小写的方式搜索列表,其中的单词必须完全匹配?谢谢


我知道这是一篇老文章,但是为了防止其他人看到,您可以使用Contains,通过提供不区分大小写的字符串相等比较器,如下所示:

1
2
3
4
if (testList.Contains(keyword, StringComparer.OrdinalIgnoreCase))
{
    Console.WriteLine("Keyword Exists");
}

根据msdn,这是从.NET 2.0开始提供的。


使用string.equals而不是string.indexof,以确保没有部分匹配。另外,不要在每个元素中使用findall,使用findindex(它在第一个元素中停止)。

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

交替使用一些LINQ方法(也会在它命中的第一个方法上停止)

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


基于上面的AdamSills答案-这里有一个很好的干净的contains扩展方法…:)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
///----------------------------------------------------------------------
/// <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)) :
        list.Contains(value);
}

可以使用StringComparer:

1
2
3
4
5
6
7
8
9
    var list = new List<string>();
    list.Add("cat");
    list.Add("dog");
    list.Add("moth");

    if (list.Contains("MOTH", StringComparer.OrdinalIgnoreCase))
    {
        Console.WriteLine("found");
    }

基于Lance Larsen的答案-这里有一个带有推荐字符串的扩展方法。比较而不是字符串。等于

It is highly recommended that you use an overload of String.Compare that takes a StringComparison parameter. Not only do these overloads allow you to define the exact comparison behavior you intended, using them will also make your code more readable for other developers. [Josh Free @ BCL Team Blog]

1
2
3
4
5
6
7
public static bool Contains(this List<string> source, string toCheck, StringComparison comp)
{
    return
       source != null &&
       !string.IsNullOrEmpty(toCheck) &&
       source.Any(x => string.Compare(x, toCheck, comp) == 0);
}

我有一个类似的问题,我需要这个项目的索引,但它必须是不区分大小写的,我环视了几分钟,没有发现任何东西,所以我只是写了一个小方法来完成它,我做了以下的事情:

1
2
3
4
5
6
7
8
9
10
11
private static int getCaseInvariantIndex(List<string> ItemsList, string searchItem)
{
    List<string> lowercaselist = new List<string>();

    foreach (string item in ItemsList)
    {
        lowercaselist.Add(item.ToLower());
    }

    return lowercaselist.IndexOf(searchItem.ToLower());
}

将此代码添加到同一个文件中,然后这样调用它:

1
int index = getCaseInvariantIndexFromList(ListOfItems, itemToFind);

希望这有帮助,祝你好运!


您正在检查indexof的结果是否大于或等于0,这意味着匹配是否从字符串中的任何位置开始。尝试检查它是否等于0:

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

现在"山羊"和"燕麦"不匹配,但"山羊"和"果阿"会匹配。为了避免这种情况,您可以比较两个字符串的长度。

为了避免所有这些复杂性,您可以使用字典而不是列表。它们的键是小写字符串,值是真正的字符串。这样,性能不会受到影响,因为您不必在每次比较中使用ToLower,但您仍然可以使用Contains