不区分大小写的搜索列表

时间:2010-10-16 00:46:53

标签: c# list search case-insensitive

我有一个包含一堆字符串的列表testList。我想在testList中添加一个新字符串,只要它在列表中不存在。因此,我需要对列表进行不区分大小写的搜索并使其有效。我不能使用Contains,因为这没有考虑到套管。出于性能原因,我也不想使用ToUpper/ToLower。我偶然发现了这种方法:

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

这样可行,但它也匹配部分单词。如果列表包含“山羊”,我不能添加“燕麦”,因为它声称“燕麦”已经在列表中。有没有办法以不区分大小写的方式有效地搜索列表,其中单词必须完全匹配?感谢

8 个答案:

答案 0 :(得分:288)

我意识到这是一篇旧帖子,但是万一其他人在看,你可以使用Contains提供不区分大小写的字符串相等比较器,如下所示:

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

根据msdn,自.net 2.0起就可以使用。

答案 1 :(得分:147)

使用String.Equals代替String.IndexOf,以确保您没有部分匹配。也不要使用FindAll,因为它遍历每个元素,使用FindIndex(它会在它命中的第一个元素上停止)。

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

或者使用一些LINQ方法(它们在第一个命中时停止)

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

答案 2 :(得分:17)

根据上面的Adam Sills回答 - 这是包含的一个很好的干净扩展方法......:)

///----------------------------------------------------------------------
/// <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);
}

答案 3 :(得分:2)

您可以使用StringComparer:

    var list = new List<string>();
    list.Add("cat");
    list.Add("dog");
    list.Add("moth");

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

答案 4 :(得分:1)

基于Lance Larsen的回答 - 这是一个带推荐字符串的扩展方法。比较而不是string.Equals

  

强烈建议您使用String.Compare的重载,该重载采用StringComparison参数。这些重载不仅允许您定义您想要的精确比较行为,使用它们还可以使您的代码对其他开发人员更具可读性。 [Josh Free @ BCL Team Blog]

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);
}

答案 5 :(得分:0)

您正在检查IndexOf的结果是否大于或等于0,表示匹配是否在字符串中任何地方开始。尝试检查它是否等于为0:

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

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

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

答案 6 :(得分:0)

我有一个类似的问题,我需要项目的索引,但它必须不区分大小写,我在网上看了几分钟,什么都没找到,所以我只是写了一个小方法来完成它,这里就是我做的:

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());
}

将此代码添加到同一文件中,并按以下方式调用:

int index = getCaseInvariantIndexFromList(ListOfItems, itemToFind);

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

答案 7 :(得分:0)

下面是在整个列表中搜索关键字并删除该项目的示例:

public class Book
{
  public int BookId { get; set; }
  public DateTime CreatedDate { get; set; }
  public string Text { get; set; }
  public string Autor { get; set; }
  public string Source { get; set; }
}

如果要删除“文本”属性中包含某些关键字的书,则可以创建关键字列表并将其从书列表中删除:

List<Book> listToSearch = new List<Book>()
   {
        new Book(){
            BookId = 1,
            CreatedDate = new DateTime(2014, 5, 27),
            Text = " test voprivreda...",
            Autor = "abc",
            Source = "SSSS"

        },
        new Book(){
            BookId = 2,
            CreatedDate = new DateTime(2014, 5, 27),
            Text = "here you go...",
            Autor = "bcd",
            Source = "SSSS"


        }
    };

var blackList = new List<string>()
            {
                "test", "b"
            }; 

foreach (var itemtoremove in blackList)
    {
        listToSearch.RemoveAll(p => p.Source.ToLower().Contains(itemtoremove.ToLower()) || p.Source.ToLower().Contains(itemtoremove.ToLower()));
    }


return listToSearch.ToList();