不区分大小写的“包含(字符串)”


2907

有没有办法使以下返回为真?

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

似乎没有允许我设置大小写敏感性的重载。.目前,我都将它们都大写,但这只是愚蠢的(我指的是上下外壳附带的i18n问题)。

更新
这个问题是古老的,从那时起,我意识到如果您希望进行全面研究,我会为一个非常广泛且困难的主题要求一个简单的答案。
在大多数情况下,在单语的英语代码库中,答案就足够了。我很怀疑,因为大多数来这里的人都属于这一类,这是最受欢迎的答案。但是,
这个答案提出了一个固有的问题,即我们无法区分不区分大小写的文本,直到我们知道两个文本是相同的文化并且我们知道该文化是什么。这可能是一个不太受欢迎的答案,但我认为它更正确,这就是为什么我将其标记为这样。

Answers:


1398

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

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

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

该解决方案对于不区分大小写的定义是透明的,该定义取决于语言。例如,英语使用第九个字母的字符I以及i大写和小写形式,而土耳其语使用29个字母长的字母的第十一和第十二个字母的字符。土耳其语的大写版本“ i”是一个陌生的字符“İ”。

因此,字符串tin在英语TIN中是相同的词,但在土耳其语中是不同的词。据我了解,一种是“精神”,另一种是拟声词。(特克斯,如果我错了,请纠正我,或者提出一个更好的例子)

总而言之,如果您知道文本所用的语言,则只能回答“这两个字符串相同但在不同情况下” 的问题。如果您不知道,则必须平底锅。考虑到英语在软件方面的霸权,您可能应该诉诸CultureInfo.InvariantCulture,因为用熟悉的方式会出错。


67
为什么不culture.CompareInfo.IndexOf(paragraph, word, CompareOptions.IgnoreCase) >= 0呢?它使用正确的区域性并且不区分大小写,不分配临时的小写字符串,并且避免了是否转换为小写并进行比较始终与不区分大小写的比较相同的问题。
2013年

9
该解决方案还通过为应作为搜索功能分配内存而不必要地污染了堆
JaredPar 2013年

15
当两个不同的字母具有相同的小写字母时,与ToLower()进行比较将从不区分大小写的IndexOf得到不同的结果。例如,在U + 0398“希腊大写字母Theta”或U + 03F4“希腊大写字母Theta符号”上调用ToLower()会导致U + 03B8“希腊小写字母Theta”,但是大写字母被认为是不同的。两种解决方案都将大写字母相同的小写字母视为不同,例如U + 0073“拉丁小写字母S”和U + 017F“拉丁小写字母Long S”,因此IndexOf解决方案看起来更加一致。
2013年

3
@Quartermeister-和BTW,我相信.NET 2和.NET4在此方面的行为有所不同,因为.NET 4始终使用NORM_LINGUISTIC_CASING而.NET 2则没有(此标志在Windows Vista中已经出现)。
Simon Mourier 2013年

10
为什么不写“ ddddfg” .IndexOf(“ Df”,StringComparison.OrdinalIgnoreCase)?

2712

您可以使用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);

3
很棒的字符串扩展方法!我已经编辑了我的代码,以检查源字符串不为null,以防止执行.IndexOf()时发生任何对象引用错误。
理查德·珀斯豪斯

8
这给出了paragraph.ToLower(culture).Contains(word.ToLower(culture))与之相同的答案,CultureInfo.InvariantCulture并且不能解决任何本地化问题。为什么事情太复杂了?stackoverflow.com/a/15464440/284795
Panic Panic

60
@ColonelPanic ToLower版本包含2个分配,在比较/搜索操作中是不必要的。为什么在不需要的情况下不必要地分配?
JaredPar

4
@Seabiscuit无法正常工作,因为它string是一个,IEnumerable<char>因此您无法使用它来查找子字符串
JaredPar 2014年

6
提示:默认为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 */
Jeppe Stig Nielsen

231

您可以这样使用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。


148

使用正则表达式的替代解决方案:

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

6
好主意,RegexOptions.IgnoreCase & RegexOptions.IgnorePatternWhitespace & RegexOptions.CultureInvariant;如果有帮助的话,我们在RegexOptions中还有很多按位组合,就像任何人一样。
Saravanan

7
必须说我更喜欢这种方法,尽管使用IsMatch保持整洁。
wonea 2011年

31
更糟糕的是,由于搜索字符串被解释为正则表达式,因此许多标点符号会导致错误的结果(或由于表达式无效而触发异常)。尝试搜索".""This is a sample string that doesn't contain the search string"。或尝试搜索"(invalid",以解决此问题。
cHao 2011年

17
@cHao:在这种情况下,Regex.Escape可能会有所帮助。当IndexOf/扩展Contains很简单(并且可以说更清晰)时,正则表达式似乎仍然不必要。
Dan Mangiarelli

6
请注意,我并不是在暗示这种Regex解决方案是最好的方法。我只是将其添加到原始发布的问题的答案列表中,“是否有办法使以下返回为真?”。
杰德

79

您总是可以先将字符串大写或小写。

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

糟糕,刚刚看到了最后一点。不区分大小写的比较*可能仍然会*执行相同的操作,并且如果性能不是问题,那么创建大写副本并进行比较不会出现问题。我本该发誓我曾经看到一个不区分大小写的比较...


122
搜索“土耳其测试” :)
Jon Skeet

7
在某些法语语言环境中,大写字母没有变音符号,因此ToUpper()可能不会比ToLower()好。我会说,如果可用,请使用适当的工具-不区分大小写的比较。
布莱尔·康拉德

5
不要使用ToUpper或ToLower,而要按乔恩·斯基特所说的去做
彼得·格法德

14
两年后又重新投票,再次看到了这一点……无论如何,我同意有比较字符串的更好方法。但是,并非所有程序都将本地化(大多数不会),并且许多程序是内部或一次性应用程序。由于我几乎不能指望为可抛弃式应用程序留下最好建议的信誉...我在继续:D
Ed S.

8
搜索“土耳其测试”是否与搜索“土耳其测试”相同?
JackAce

54

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

自2.0版以来,.NET Core有两种方法可以解决此问题:

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

例:

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

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


1
现在同时有.NET 2.1标准
帕维尔Bulwan

52

答案的一个问题是,如果字符串为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;
} 

8
如果toCheck是空字符串,则需要按照Contains文档中的说明返回true:“如果value参数出现在该字符串中,或​​者value是空字符串(“”),则返回true;否则,返回false。
amurra 2011年

3
根据上述amurra的评论,建议的代码是否需要更正?难道这不应该添加到已接受的答案中,以便最佳响应是第一位的吗?
大卫·怀特

13
现在,如果source为空字符串或null(无论toCheck是什么),它将返回true。那是不正确的。如果toCheck为空字符串且source不为null,则IndexOf也已返回true。这里需要检查是否为空。我建议如果(source == null || value == null)返回false;
科林2013年

2
来源不能为空
Lucas

1
if (string.IsNullOrEmpty(source)) return string.IsNullOrEmpty(toCheck);
凯尔·德莱尼

35

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

为什么要允许另一个抽象层StringComparison呢?
l --''''''---------''''''''''''

35

这是干净而简单的。

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

31
不过,这将与模式匹配。在你的榜样,如果fileNamestr有任何特殊的正则表达式字符(例如*+.等),那么你将在相当长的一个惊喜。使此解决方案像正常Contains功能一样起作用的唯一方法是fileNamestr通过执行逃脱Regex.Escape(fileNamestr)
XåpplI'-I0llwlg'I -

此外,解析和匹配正则表达式比简单的不区分大小写的比较要耗费大量资源
phuclv

29

顺序忽略案例,当前文化忽略案例还是不变文化忽略案例?

由于缺少此功能,因此以下是有关何时使用哪个的一些建议:

多斯

  • 使用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
}

而[您的决定]取决于上面的建议。

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


如果您知道您总是会得到一个英语字符串怎么办。使用哪一个?
BKSpurgeon '17

1
@BKSpurgeon我会使用OrdinalIgnoreCase,如果大小写无关紧要
Fabian Bigler

20

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

  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.IsMatch(title, "string", RegexOptions.IgnoreCase);

11

我知道这不是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");

11

InStr如果您担心国际化(或者可以重新实现),则VisualBasic程序集中的方法是最好的。查看其中的dotNeetPeek不仅显示了大写和小写字母,还显示了假名类型以及全角和半角字符(主要与亚洲语言相关,尽管也有罗马字母的全角版本) )。我跳过了一些细节,但是请查看private方法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);
}


8

用这个:

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

26
发问者寻找的Contains不是Compare
DuckMaestro'7

@DuckMaestro,接受的答案正在实施ContainsIndexOf。因此,这种方法同样有用!本页上的C#代码示例使用string.Compare()。是SharePoint团队的选择!
火神乌鸦

6

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

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

6

使用RegEx是执行此操作的直接方法:

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

4
您的答案与guptat59的答案完全相同,但正如他在答案中所指出的那样,它将匹配一个正则表达式,因此,如果您正在测试的字符串包含任何特殊的正则表达式字符,则不会产生预期的结果。
Casey 2013年

2
这是此答案的直接副本,并且遇到与该答案相同的问题
Liam

同意 研究正则表达式
Jared

5

只是基于此处的答案,您可以创建一个字符串扩展方法以使其更加人性化:

    public static bool ContainsIgnoreCase(this string paragraph, string word)
    {
        return CultureInfo.CurrentCulture.CompareInfo.IndexOf(paragraph, word, CompareOptions.IgnoreCase) >= 0;
    }

1
假设你的段落和字永远是EN-US
鲍里斯Callens

3
为避免强迫文化进入美国的问题,请return CultureInfo.CurrentCulture.CompareInfo.IndexOf(paragraph, word, CompareOptions.IgnoreCase) >= 0;改用。
AndrewWhalan

3

如果要检查传递的字符串是否在字符串中,则有一个简单的方法。

string yourStringForCheck= "abc";
string stringInWhichWeCheck= "Test abc abc";

bool isContained = stringInWhichWeCheck.ToLower().IndexOf(yourStringForCheck.ToLower()) > -1;

如果包含或不包含字符串,则返回此布尔值





2

这里的技巧是查找字符串,忽略大小写,但要使其完全相同(大小写相同)。

 var s="Factory Reset";
 var txt="reset";
 int first = s.IndexOf(txt, StringComparison.InvariantCultureIgnoreCase) + txt.Length;
 var subString = s.Substring(first - txt.Length, txt.Length);

输出为“重置”


-1
public static class StringExtension
{
    #region Public Methods

    public static bool ExContains(this string fullText, string value)
    {
        return ExIndexOf(fullText, value) > -1;
    }

    public static bool ExEquals(this string text, string textToCompare)
    {
        return text.Equals(textToCompare, StringComparison.OrdinalIgnoreCase);
    }

    public static bool ExHasAllEquals(this string text, params string[] textArgs)
    {
        for (int index = 0; index < textArgs.Length; index++)
            if (ExEquals(text, textArgs[index]) == false) return false;
        return true;
    }

    public static bool ExHasEquals(this string text, params string[] textArgs)
    {
        for (int index = 0; index < textArgs.Length; index++)
            if (ExEquals(text, textArgs[index])) return true;
        return false;
    }

    public static bool ExHasNoEquals(this string text, params string[] textArgs)
    {
        return ExHasEquals(text, textArgs) == false;
    }

    public static bool ExHasNotAllEquals(this string text, params string[] textArgs)
    {
        for (int index = 0; index < textArgs.Length; index++)
            if (ExEquals(text, textArgs[index])) return false;
        return true;
    }

    /// <summary>
    /// Reports the zero-based index of the first occurrence of the specified string
    /// in the current System.String object using StringComparison.InvariantCultureIgnoreCase.
    /// A parameter specifies the type of search to use for the specified string.
    /// </summary>
    /// <param name="fullText">
    /// The string to search inside.
    /// </param>
    /// <param name="value">
    /// The string to seek.
    /// </param>
    /// <returns>
    /// The index position of the value parameter if that string is found, or -1 if it
    /// is not. If value is System.String.Empty, the return value is 0.
    /// </returns>
    /// <exception cref="ArgumentNullException">
    /// fullText or value is null.
    /// </exception>
    public static int ExIndexOf(this string fullText, string value)
    {
        return fullText.IndexOf(value, StringComparison.OrdinalIgnoreCase);
    }

    public static bool ExNotEquals(this string text, string textToCompare)
    {
        return ExEquals(text, textToCompare) == false;
    }

    #endregion Public Methods
}

-4

新手的简单方法:

title.ToLower().Contains("string");//of course "string" is lowercase.

因不正确而投降。如果标题= StRiNg怎么办?StRiNg!=字符串,而StRiNg!= STRING
berniefitz

我错了。编辑答案如下,太简单了:<br/> title.ToLower()。Contains(“ string”)//当然“ string”是小写字母
OThạnhLdt
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.