我有一个包含一堆字符串的列表testList
。我想在testList
中添加一个新字符串,只要它在列表中不存在。因此,我需要对列表进行不区分大小写的搜索并使其有效。我不能使用Contains
,因为这没有考虑到套管。出于性能原因,我也不想使用ToUpper/ToLower
。我偶然发现了这种方法:
if(testList.FindAll(x => x.IndexOf(keyword,
StringComparison.OrdinalIgnoreCase) >= 0).Count > 0)
Console.WriteLine("Found in list");
这样可行,但它也匹配部分单词。如果列表包含“山羊”,我不能添加“燕麦”,因为它声称“燕麦”已经在列表中。有没有办法以不区分大小写的方式有效地搜索列表,其中单词必须完全匹配?感谢
答案 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();