不区分大小写'包含(字符串)'

Boris Callens 2591 c# string contains case-insensitive

有没有办法让以下返回true?

string title = "ASTRINGTOTEST";
title.Contains("string");

似乎没有一个过载允许我设置区分大小写.目前我大写它们两个,但这只是愚蠢(我指的是上下套管的i18n问题).

更新
这个问题是古老的,从那时起我就意识到,如果你想完全研究它,我会要求一个简单的答案来解决一个非常庞大和困难的话题.
对于大多数情况,在单语言的英语代码库中,这个答案就足够了.我怀疑是因为大多数人来到这个类别这是最受欢迎的答案.然而,
这个答案提出了一个固有的问题,即我们无法比较文本不区分大小写,直到我们知道两个文本是相同的文化并且我们知道文化是什么.这可能是一个不太受欢迎的答案,但我认为它更正确,这就是为什么我这样标记它.

JaredPar.. 2486

您可以使用String.IndexOf方法并将其StringComparison.OrdinalIgnoreCase作为要使用的搜索类型传递:

string title = "STRING";
bool contains = title.IndexOf("string", StringComparison.OrdinalIgnoreCase) >= 0;

更好的是为字符串定义一个新的扩展方法:

public static class StringExtensions
{
    public static bool Contains(this string source, string toCheck, StringComparison comp)
    {
        return source?.IndexOf(toCheck, comp) >= 0;
    }
}

请注意,对于旧版本,C#6.0(VS 2015)可以使用空传播 ?.

if (source == null) return false;
return source.IndexOf(toCheck, comp) >= 0;

用法:

string title = "STRING";
bool contains = title.Contains("string", StringComparison.OrdinalIgnoreCase);

  • @ColonelPanic`ToLower`版本包括2个分配,这些分配在比较/搜索操作中是不必要的.为什么在不需要它的场景中进行不必要的分配? (47认同)
  • 这给出了与`paragraph.ToLower(culture).Contains(word.ToLower(culture))`和`CultureInfo.InvariantCulture`相同的答案,并没有解决任何本地化问题.为什么复杂的事情?http://stackoverflow.com/a/15464440/284795 (7认同)
  • @Seabiscuit无效,因为`string`是一个`IEnumerable <char>`因此你不能用它来查找子串 (4认同)
  • 一句警告:`string.IndexOf(string)`的默认值是使用当前文化,而`string.Contains(string)`的默认值是使用序数比较器.众所周知,前者可以改变选择较长的过载,而后者不能改变.这种不一致的结果是以下代码示例:`Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture; string self ="Waldstrasse"; string value ="straße"; Console.WriteLine(self.Contains(value));/*False*/Console.WriteLine(self.IndexOf(value)> = 0);/*True*/` (4认同)
  • 伟大的字符串扩展方法 我编辑了我的,检查源字符串是否为null,以防止在执行.IndexOf()时发生任何对象引用错误. (2认同)
  • 源如何才能为空?这是一种扩展方法. (2认同)

Colonel Pani.. 1202

测试字符串是否paragraph包含字符串word(感谢@QuarterMeister)

culture.CompareInfo.IndexOf(paragraph, word, CompareOptions.IgnoreCase) >= 0

描述文本所用语言culture的实例在哪里CultureInfo.

这种解决方案对于不区分大小写的定义是透明的,这种定义与语言有关.例如,英语使用字符Ii第九个字母的大写和小写版本,而土耳其语使用这些字符作为其29个字母长字母的第11和第12个字母.土耳其大写版本的'i'是不熟悉的角色'İ'.

因此,串tinTIN是同一个词在英语,但不同的词在土耳其.据我所知,一个是"精神",另一个是拟声词.(土耳其人,请纠正我,如果我错了,或建议一个更好的例子)

总而言之,如果您知道文本所使用的语言,则只能回答"这两个字符串是否相同但在不同情况下" 的问题.如果你不知道,你将不得不采取行动.鉴于英语在软件方面的霸权,你应该诉诸于此CultureInfo.InvariantCulture,因为以熟悉的方式会出错.

  • 为什么不`culture.CompareInfo.IndexOf(paragraph,word,CompareOptions.IgnoreCase)> = 0`?它使用正确的文化并且不区分大小写,它不分配临时小写字符串,并且它避免了转换为小写和比较是否总是与不区分大小写的比较相同的问题. (57认同)
  • 完整性为+1 - 具有适当解释形式的答案是用户实际从SO中学习的唯一方式 (17认同)
  • 当两个不同的字母具有相同的小写字母时,与ToLower()比较将给出不区分大小写的IndexOf的不同结果.例如,在U + 0398"希腊大写字母Theta"或U + 03F4"希腊大写字母Theta符号"上调用ToLower()会产生U + 03B8,"希腊小写字母Theta",但大写字母被认为是不同的.两种解决方案都考虑使用相同大写字母的小写字母不同,例如U + 0073"Latin Small Letter S"和U + 017F"Latin Small Letter Long S",因此IndexOf解决方案似乎更加一致. (15认同)
  • 此解决方案还通过为应该是搜索功能的内存分配内存来不必要地污染堆 (9认同)
  • 你为什么不写"ddddfg".IndexOf("Df",StringComparison.OrdinalIgnoreCase)? (6认同)
  • 是的,你对土耳其语非常正确.ı=>我,我=>İ (4认同)
  • @Quartermeister - 和BTW,我相信.NET 2和.NET4在这方面表现不同,因为.NET 4总是使用NORM_LINGUISTIC_CASING而.NET 2没有(这个标志出现在Windows Vista中). (3认同)

mkchandler.. 212

你可以IndexOf()像这样使用:

string title = "STRING";

if (title.IndexOf("string", 0, StringComparison.CurrentCultureIgnoreCase) != -1)
{
    // The string exists in the original
}

由于0(零)可以是索引,因此请检查-1.

MSDN

如果找到该字符串,则从零开始的索引位置值,如果不是,则返回-1.如果value为String.Empty,则返回值为0.


Jed.. 121

使用Regex的替代解决方案:

bool contains = Regex.IsMatch("StRiNG to search", Regex.Escape("string"), RegexOptions.IgnoreCase);

  • 更糟糕的是,由于搜索字符串被解释为正则表达式,因此许多标点字符将导致错误的结果(或由于表达式无效而触发异常).尝试搜索`"."````这是一个不包含搜索字符串的示例字符串"`.或者尝试搜索""(无效"`,就此而言. (26认同)
  • @cHao:在这种情况下,`Regex.Escape`可以提供帮助.当`IndexOf`/extension`Contains`简单(并且可以说更清楚)时,正则表达式似乎仍然没有必要. (13认同)
  • 必须说我更喜欢这种方法,尽管使用IsMatch来保持整洁. (7认同)
  • 好主意,我们在RegexOptions中有很多按位组合,例如`RegexOptions.IgnoreCase&RegexOptions.IgnorePatternWhitespace&RegexOptions.CultureInvariant;`对于任何人都有帮助. (5认同)
  • 请注意,我并不是说这个Regex解决方案是最好的方法.我只是添加到原始发布问题的答案列表中"是否有办法使以下返回成立?". (5认同)
  • 这将比使用IndexOf效率大大降低.使用正则表达式会增加更多的处理时间,内存等. (2认同)

Ed S... 70

您可以先将字符串向上或向下放大.

string title = "string":
title.ToUpper().Contains("STRING")  // returns true

哎呀,刚看到最后一点.不区分大小写的比较可能**做同样的事情,如果性能不是问题,我没有看到创建大写副本和比较它们的问题.我曾经发誓我曾经看过一次不区分大小写的比较...

  • 搜索"土耳其测试":) (105认同)
  • 两年后再次看到这个和一个新的downvote ...无论如何,我同意有更好的方法来比较字符串.但是,并非所有程序都将本地化(大多数不会),许多程序是内部或一次性应用程序.因为对于一次性应用程序最好的建议,我几乎不能指望获得信用......我正在继续:D (12认同)
  • 在一些法语语言环境中,大写字母没有变音符号,因此ToUpper()可能不比ToLower()好.如果它们可用,我会说使用适当的工具 - 不区分大小写的比较. (5认同)
  • 不要使用ToUpper或ToLower,并做Jon Skeet所说的 (4认同)
  • 有趣的是,我已经看到ToUpper()在这种情况下推荐使用ToLower(),因为显然ToLower()在某些文化中可能"失去保真度" - 也就是说,两个不同的大写字符转换为相同的小写字符. (3认同)
  • 正在搜索"土耳其测试"和搜索"土耳其测试"一样吗? (3认同)

大智慧.. 48

答案的一个问题是,如果字符串为null,它将抛出异常.您可以将其添加为支票,因此不会:

public static bool Contains(this string source, string toCheck, StringComparison comp)
{
    if (string.IsNullOrEmpty(toCheck) || string.IsNullOrEmpty(source))
        return true;

    return source.IndexOf(toCheck, comp) >= 0;
} 

  • 现在,如果source是空字符串,则返回true,无论toCheck是什么,这都将返回null.这不可能是正确的.如果toCheck为空字符串且source不为null,则IndexOf也会返回true.这里需要检查null.我建议if(source == null || value == null)返回false; (11认同)
  • 如果toCheck是空字符串,则需要根据Contains文档返回true:"如果value参数出现在此字符串中,则为true,或者如果value为空字符串("");否则为false." (8认同)
  • 根据上述amurra的评论,建议的代码是否需要更正?并且不应该将其添加到已接受的答案中,以便最好的响应是第一个? (3认同)
  • 源不能为空 (2认同)

Andrew.. 34

StringExtension类是前进的方法,我结合上面的几个帖子给出了一个完整的代码示例:

public static class StringExtensions
{
    /// <summary>
    /// Allows case insensitive checks
    /// </summary>
    public static bool Contains(this string source, string toCheck, StringComparison comp)
    {
        return source.IndexOf(toCheck, comp) >= 0;
    }
}


takirala.. 34

这很简洁.

Regex.IsMatch(file, fileNamestr, RegexOptions.IgnoreCase)

  • 但这将与模式匹配.在你的例子中,如果`fileNamestr`有任何特殊的正则表达式字符(例如`*`,`+`,`.`等),那么你将会非常惊讶.使这个解决方案像正确的`Contains`函数一样工作的唯一方法是通过`Regex.Escape(fileNamestr)`来逃避`fileNamestr`. (24认同)

Fabian Bigle.. 24

OrdinalIgnoreCase,CurrentCultureIgnoreCase还是InvariantCultureIgnoreCase?

由于缺少这个,这里有一些关于何时使用哪一个的建议:

DOS

  • 使用StringComparison.OrdinalIgnoreCase的比较作为默认的安全文化无关的字符串匹配.
  • 使用StringComparison.OrdinalIgnoreCase比较来提高速度.
  • StringComparison.CurrentCulture-based向用户显示输出时使用字符串操作.
  • 切换基于不变文化的字符串操作的当前使用以使用非语言StringComparison.OrdinalStringComparison.OrdinalIgnoreCase当比较在
    语言上不相关时(例如,符号).
  • 使用ToUpperInvariant而不是ToLowerInvariant将字符串规范化以进行比较.

注意事项

  • 对未明确或隐式指定字符串比较机制的字符串操作使用重载.
  • 在大多数情况下使用StringComparison.InvariantCulture基于字符串的
    操作; 少数例外之一是
    持久的语言有意义但与文化无关的数据.

根据这些规则,您应该使用:

string title = "STRING";
if (title.IndexOf("string", 0, StringComparison.[YourDecision]) != -1)
{
    // The string exists in the original
}

而[YourDecision]取决于上述建议.

来源链接:http://msdn.microsoft.com/en-us/library/ms973919.aspx


Mathieu Rend.. 12

仅限.NET Core 2.0+(截至目前)

从2.0版开始,.NET Core有一对处理这个问题的方法:

  • String.Contains(Char,StringComparison)
  • String.Contains(String,StringComparison)

例:

"Test".Contains("test", System.StringComparison.CurrentCultureIgnoreCase);

随着时间的推移,他们可能会进入.NET标准,并从那里进入基类库的所有其他实现.

  • 最后!花了很长时间才有空...... (2认同)

大智慧.. 11

这些是最简单的解决方案.

  1. 按索引

    string title = "STRING";
    
    if (title.IndexOf("string", 0, StringComparison.CurrentCultureIgnoreCase) != -1)
    {
        // contains 
    }
    
  2. 通过改变案例

    string title = "STRING";
    
    bool contains = title.ToLower().Contains("string")
    
  3. 通过Regex

    Regex.IsMatch(title, "string", RegexOptions.IgnoreCase);
    


serhio.. 10

我知道这不是C#,但在框架(VB.NET)中已经存在这样的功能

Dim str As String = "UPPERlower"
Dim b As Boolean = InStr(str, "UpperLower")

C#变种:

string myString = "Hello World";
bool contains = Microsoft.VisualBasic.Strings.InStr(myString, "world");


Casey.. 10

InStr如果您对国际化有所顾虑(或者您可以重新实现),那么VisualBasic程序集中的方法是最好的.在它看来dotNeetPeek显示它不仅占大写字母和小写字母,而且还包括假名类型和全角度与半宽字符(主要与亚洲语言相关,尽管罗马字母也有全宽版本) ).我正在跳过一些细节,但查看私有方法InternalInStrText:

private static int InternalInStrText(int lStartPos, string sSrc, string sFind)
{
  int num = sSrc == null ? 0 : sSrc.Length;
  if (lStartPos > num || num == 0)
    return -1;
  if (sFind == null || sFind.Length == 0)
    return lStartPos;
  else
    return Utils.GetCultureInfo().CompareInfo.IndexOf(sSrc, sFind, lStartPos, CompareOptions.IgnoreCase | CompareOptions.IgnoreKanaType | CompareOptions.IgnoreWidth);
}


cdytoby.. 10

像这样:

string s="AbcdEf";
if(s.ToLower().Contains("def"))
{
    Console.WriteLine("yes");
}

  • 这不是特定于文化的,在某些情况下可能会失败.culture.CompareInfo.IndexOf(段落,单词,CompareOptions.IgnoreCase)应该被使用. (2认同)
  • [为什么在进行不区分大小写的字符串比较时避免使用string.ToLower()?](http://stackoverflow.com/questions/28440783/why-avoid-string-tolower-when-doing-case-insensitive-string-comparisons) Tl; Dr*这是昂贵的,因为新的字符串是"制造的".* (2认同)

大智慧.. 9

用这个:

string.Compare("string", "STRING", new System.Globalization.CultureInfo("en-US"), System.Globalization.CompareOptions.IgnoreCase);

  • 提问者正在寻找`Contains`而不是`Compare`. (25认同)

大智慧.. 6

使用RegEx是一种直接的方法:

Regex.IsMatch(title, "string", RegexOptions.IgnoreCase);

  • 你的答案与guptat59完全一样,但正如他的回答所指出的,这将匹配正则表达式,所以如果你正在测试的字符串包含任何特殊的正则表达式字符,它将不会产生所需的结果. (4认同)
  • 这是[此答案](http://stackoverflow.com/a/13302103/542251)的直接副本,并且遇到与该答案中所述相同的问题 (2认同)

TarmoPikaro.. 5

这与此处的其他示例非常相似,但我决定将枚举简化为bool,primary,因为通常不需要其他替代方法.这是我的例子:

public static class StringExtensions
{
    public static bool Contains(this string source, string toCheck, bool bCaseInsensitive )
    {
        return source.IndexOf(toCheck, bCaseInsensitive ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal) >= 0;
    }
}

用法如下:

if( "main String substring".Contains("SUBSTRING", true) )
....


归档时间:

查看次数:

743337 次

最近记录:

9 月,1 周 前