不区分大小写列表搜索

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

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

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

177472 次浏览

而不是字符串。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");

您正在检查IndexOf的结果是否大于或等于0,这意味着匹配是否从字符串中的在任何地方开始。试着检查它是否从平等的到0:

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

“goat”和“oat”不匹配,但“goat”和“goa”可以。为了避免这种情况,可以比较两个字符串的长度。

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

基于Adam Sills上面的回答——这里有一个很好的、干净的Contains扩展方法…:)

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

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

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

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

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

using System.Linq;


// ...


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

根据msdn,自。net 2.0以来已经可用。

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

强烈建议您使用String的重载。它接受一个stringcompare参数。这些重载不仅允许您定义您想要的准确比较行为,使用它们还将使您的代码对其他开发人员更具可读性。(Josh Free @ BCL团队博客)

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

例如,你可以从LINQ中使用StringComparer静态变量和Contains重载,如下所示:

using System.Linq;


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


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

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

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