不区分大小写的“Contains(string)”

Case insensitive 'Contains(string)'

提问人:Boris Callens 提问时间:1/15/2009 最后编辑:Uwe KeimBoris Callens 更新时间:6/20/2023 访问量:1210929

问:

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

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

似乎没有允许我设置区分大小写的重载。目前我把它们都大写,但这很愚蠢(我指的是上下大小写的 i18n 问题)。

更新

这个问题由来已久,从那时起,我意识到,如果你愿意全面调查它,我要求对一个非常庞大而困难的话题有一个简单的答案。

在大多数情况下,在单语英语代码库中,这个答案就足够了。我怀疑,因为大多数来这里的人都属于这一类,这是最受欢迎的答案。

然而,这个答案带来了一个固有的问题,即在我们知道两个文本是相同的文化并且我们知道这种文化是什么之前,我们无法比较不区分大小写的文本。这可能是一个不太受欢迎的答案,但我认为它更正确,这就是我这样标记它的原因。

C# 字符串 包含 不区分大小写的

评论


答:

101赞 Ed S. 1/15/2009 #1

您始终可以先将字符串放大或缩小。

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

哎呀,刚刚看到了最后一点。无论如何,不区分大小写的比较可能会做同样的事情,如果性能不是问题,我认为创建大写副本并比较这些副本没有问题。我可以发誓,我曾经看过一次不区分大小写的比较......**

评论

144赞 Jon Skeet 1/15/2009
搜索“土耳其测试”:)
10赞 Blair Conrad 1/15/2009
在某些法语语言环境中,大写字母没有变音符号,因此 ToUpper() 可能并不比 ToLower() 好。我会说,如果可用,请使用适当的工具 - 不区分大小写的比较。
7赞 Peter Gfader 8/21/2009
不要使用 ToUpper 或 ToLower,并按照 Jon Skeet 所说的去做
19赞 Ed S. 1/25/2011
两年后又看到了这个,又投了新的反对票......无论如何,我同意有更好的方法来比较字符串。但是,并非所有程序都会本地化(大多数不会),并且许多程序是内部或一次性应用程序。因为我很难指望最好留给一次性应用程序的建议的功劳......我正在继续前进:D
13赞 JackAce 6/2/2018
搜索“土耳其测试”和搜索“土耳其测试”一样吗?
3109赞 JaredPar 1/15/2009 #2

可以使用 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) 起,null 传播可用,对于旧版本使用?.

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

用法:

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

评论

5赞 Richard Pursehouse 2/8/2013
很棒的字符串扩展方法!我已经编辑了我的以检查源字符串是否为空,以防止在执行时发生任何对象引用错误。IndexOf() 中。
13赞 Colonel Panic 3/18/2013
这给出了与 with 相同的答案,并且没有解决任何本地化问题。为什么要把事情复杂化?stackoverflow.com/a/15464440/284795paragraph.ToLower(culture).Contains(word.ToLower(culture))CultureInfo.InvariantCulture
87赞 JaredPar 3/19/2013
@ColonelPanic版本包括 2 个分配,这在比较/搜索操作中是不必要的。为什么在不需要的情况下进行不必要的分配?ToLower
6赞 JaredPar 11/7/2014
@Seabiscuit这不起作用,因为您不能使用它来查找子字符串stringIEnumerable<char>
17赞 Jeppe Stig Nielsen 2/18/2016
警告:默认值 for 是使用当前区域性,而默认值是使用序号比较器。众所周知,前者可以通过选择更长的过载来更改,而后者则无法更改。这种不一致的结果是以下代码示例: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 */
275赞 mkchandler 1/15/2009 #3

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

string title = "STRING";

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

由于 0(零)可以是索引,因此您可以针对 -1 进行检查。

Microsoft .NET 文档:

如果找到该字符串,则从当前实例的开头开始的 value 参数的从零开始的索引位置,如果未找到该字符串,则为 -1。如果 value 为 Empty,则返回值为 startIndex。

158赞 Jed 7/29/2010 #4

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

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

评论

7赞 Saravanan 8/24/2011
好主意,我们在RegexOptions中也有很多按位组合,就像任何人一样,如果有帮助的话。RegexOptions.IgnoreCase & RegexOptions.IgnorePatternWhitespace & RegexOptions.CultureInvariant;
8赞 wonea 9/8/2011
必须说我更喜欢这种方法,尽管使用 IsMatch 来保持整洁。
38赞 cHao 9/9/2011
更糟糕的是,由于搜索字符串被解释为正则表达式,因此许多标点符号字符将导致不正确的结果(或由于无效的表达式而触发异常)。尝试在 中搜索。或者尝试搜索 ,就此而言。".""This is a sample string that doesn't contain the search string""(invalid"
21赞 Dan Mangiarelli 9/10/2011
@cHao:在这种情况下,可能会有所帮助。当/扩展很简单(并且可以说更清晰)时,正则表达式似乎仍然没有必要。Regex.EscapeIndexOfContains
9赞 Jed 9/13/2011
请注意,我并不是在暗示这个正则表达式解决方案是最好的方法。我只是在回答原始发布的问题“有没有办法使以下返回成为现实?
41赞 Andrew 11/19/2010 #5

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

评论

1赞 Alex Gordon 6/21/2019
你为什么要允许另一层抽象?StringComparison
2赞 Josh 1/6/2021
因为这简化了代码的读取和写入。它实质上是在模仿后来版本的 .Net 直接添加到类中的内容。对于简单的便捷方法,有很多话要说,这些方法使您和他人的生活更轻松,即使它们确实增加了一点抽象。
54赞 FeiBao 飞豹 12/8/2010 #6

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

评论

9赞 amurra 2/17/2011
如果 toCheck 是空字符串,则需要根据 Contains 文档返回 true:“true 如果 value 参数出现在此字符串中,或者 value 是空字符串 (”“);否则,为 false。
4赞 David White 8/30/2011
根据上面 amurra 的评论,建议的代码不需要更正吗?难道不应该将其添加到公认的答案中,以便最好的答案是第一位的吗?
16赞 Colin 7/1/2013
现在,如果 source 是空字符串或 null,则无论 toCheck 是什么,这将返回 true。这是不正确的。此外,如果 toCheck 为空字符串且 source 不为 null,则 IndexOf 已返回 true。这里需要的是 null 的检查。我建议如果 (source == null || value == null) 返回 false;
3赞 Lucas 12/15/2016
源不能为 null
3赞 Kyle Delaney 4/4/2018
if (string.IsNullOrEmpty(source)) return string.IsNullOrEmpty(toCheck);
10赞 mr.martan 7/11/2011 #7

使用这个:

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

评论

29赞 DuckMaestro 7/11/2011
提问者正在寻找的不是.ContainsCompare
1赞 vulcan raven 1/5/2013
@DuckMaestro,公认的答案是用 实现。所以这种方法同样有用!此页上的 C# 代码示例使用字符串。比较()。SharePoint 团队的选择就是这样!ContainsIndexOf
12赞 serhio 9/9/2011 #8

我知道这不是 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");
36赞 takirala 11/9/2012 #9

这既干净又简单。

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

评论

34赞 XåpplI'-I0llwlg'I - 2/3/2013
不过,这将与模式相匹配。在您的示例中,如果有任何特殊的正则表达式字符(例如、、等),那么您会感到非常惊讶。使此解决方案像正常工作功能一样工作的唯一方法是通过执行 来逃避。fileNamestr*+.ContainsfileNamestrRegex.Escape(fileNamestr)
2赞 phuclv 11/30/2019
此外,解析和匹配正则表达式比简单的不区分大小写的比较更耗费资源
1576赞 Colonel Panic 3/18/2013 #10

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

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

其中 是描述编写文本所用语言的 CultureInfo 实例。culture

此解决方案对不区分大小写的定义是透明的,这与语言有关。例如,英语使用字符和第九个字母的大小写版本,而土耳其语则将这些字符用于其 29 个字母长的字母表中的第 11 个和第 12 个字母。土耳其语大写字母“i”是陌生的字符“İ”。Ii

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

总而言之,如果您知道文本使用的语言,您只能回答“这两个字符串是否相同但在不同情况下”的问题。如果你不知道,你将不得不下注。鉴于英语在软件领域的霸权地位,您可能应该求助于 CultureInfo.InvariantCulture,因为它以熟悉的方式是错误的。

评论

79赞 Quartermeister 3/18/2013
为什么不呢?它使用正确的区域性并且不区分大小写,它不会分配临时的小写字符串,并且它避免了转换为小写和比较是否始终与不区分大小写的比较相同的问题。culture.CompareInfo.IndexOf(paragraph, word, CompareOptions.IgnoreCase) >= 0
11赞 JaredPar 3/19/2013
此解决方案还通过为本应是搜索函数的函数分配内存来不必要地污染堆
19赞 Quartermeister 3/19/2013
当两个不同的字母具有相同的小写字母时,与 ToLower() 进行比较将给出与不区分大小写的 IndexOf 不同的结果。例如,对 U+0398“希腊大写字母 Theta”或 U+03F4“希腊大写字母 Theta 符号”调用 ToLower() 会导致 U+03B8“希腊小写字母 Theta”,但大写字母被视为不同。这两种解决方案都考虑了具有相同大写字母的不同小写字母,例如 U+0073“拉丁文小写字母 S”和 U+017F“拉丁文小写字母长 S”,因此 IndexOf 解决方案似乎更一致。
3赞 Simon Mourier 3/23/2013
@Quartermeister - 顺便说一句,我相信 .NET 2 和 .NET4 在这方面的行为有所不同,因为 .NET 4 始终使用 NORM_LINGUISTIC_CASING,而 .NET 2 则不使用(此标志已出现在 Windows Vista 中)。
12赞 Chen 8/23/2015
你为什么不写“ddddfg”。IndexOf(“Df”, StringComparison.OrdinalIgnoreCase) ?
7赞 Stend 9/18/2013 #11

使用正则表达式是实现此目的的直接方法:

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

评论

7赞 Casey 12/10/2013
您的答案与 guptat59 的答案完全相同,但正如他的答案中指出的那样,这将与正则表达式匹配,因此,如果您正在测试的字符串包含任何特殊的正则表达式字符,则不会产生所需的结果。
3赞 Liam 10/10/2016
这是此答案的直接副本,并且存在与该答案中指出的相同问题
1赞 Jar 12/26/2017
同意。研究正则表达式
11赞 Casey 12/6/2013 #12

如果您担心国际化(或者可以重新实现它),则 VisualBasic 程序集中的方法是最佳方法。从dotNeetPeek中可以看出,它不仅考虑了大写字母和小写字母,还考虑了假名类型和全角与半角字符(主要与亚洲语言有关,尽管罗马字母也有全角版本)。我跳过了一些细节,但请查看私有方法:InStrInternalInStrText

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);
}
36赞 Fabian Bigler 6/17/2014 #13

OrdinalIgnoreCase、CurrentCultureIgnoreCase 还是 InvariantCultureIgnoreCase?

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

  • 用于比较 作为与区域性无关的字符串匹配的安全默认值。StringComparison.OrdinalIgnoreCase
  • 使用比较 以提高速度。StringComparison.OrdinalIgnoreCase
  • 使用字符串操作 向用户显示输出时。StringComparison.CurrentCulture-based
  • 根据不变性切换字符串操作的当前使用情况 文化,使用非语言或当比较在
    语言上无关紧要时(例如,符号)。
    StringComparison.OrdinalStringComparison.OrdinalIgnoreCase
  • 使用而不是何时使用 规范化字符串以进行比较。ToUpperInvariantToLowerInvariant

注意 事项

  • 对未显式执行的字符串操作使用重载 或隐式指定字符串比较机制。
  • 在大多数情况下使用基于字符串
    的操作;为数不多的例外之一是
    保留具有语言意义但与文化无关的数据。
    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

评论

1赞 BenKoshy 3/24/2017
如果你知道你总是会得到一个英文字符串怎么办。使用哪一个?
2赞 Fabian Bigler 3/24/2017
@BKSpurgeon我会使用 OrdinalIgnoreCase,如果大小写无关紧要
1赞 Jeff 9/30/2021
为什么我们更喜欢 ToUpperInvariant 而不是 ToLowerInvariant?
14赞 cdytoby 7/13/2014 #14

就像这样:

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

评论

4赞 hikalkan 7/22/2014
这不是特定于区域性的,在某些情况下可能会失败。文化。应使用 CompareInfo.IndexOf(paragraph, word, CompareOptions.IgnoreCase)。
4赞 Liam 10/10/2016
为什么要避免字符串。ToLower() 在进行不区分大小写的字符串比较时?Tl;博士:这很昂贵,因为新弦是“制造”的。
7赞 TarmoPikaro 10/17/2015 #15

这与此处的其他示例非常相似,但我决定将枚举简化为 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) )
....
3赞 Mr.B 5/3/2016 #16

这里的诀窍是查找字符串,忽略大小写,但保持完全相同(大小写相同)。

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

输出为“Reset”

3赞 Tamilselvan K 10/26/2016 #17
if ("strcmpstring1".IndexOf(Convert.ToString("strcmpstring2"), StringComparison.CurrentCultureIgnoreCase) >= 0){return true;}else{return false;}
3赞 Okan SARICA 12/11/2016 #18

您可以使用函数。这将不区分大小写string.indexof ()

-3赞 O Thạnh Ldt 4/17/2017 #19

新手的简单方法:

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

评论

1赞 bernieslearnings 10/21/2017
仅仅因为不正确而投反对票。如果标题 = StRiNg 怎么办?StRiNg != 字符串和 StRiNg != 字符串
2赞 O Thạnh Ldt 3/23/2018
我错了。编辑答案如下,太简单了 simple:<br/>title。ToLower() 中。Contains(“string”) // 当然“string”是小写的
1赞 Final Heaven 6/14/2017 #20
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
}
5赞 shaishav shukla 11/16/2017 #21

如果你想检查你传递的字符串是否在字符串中,那么有一个简单的方法。

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

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

如果字符串是否包含,则此布尔值将返回

27赞 Lav Vishwakarma 7/12/2018 #22

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

  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);
    
205赞 Mathieu Renda 10/13/2018 #23

.NET Core 2.0+(包括 .NET 5.0+).NET Core 2.0+ (including .NET 5.0+)

自2.0版以来,.NET Core已经有一对方法来处理这个问题:

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

例:

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

它现在是 .NET Standard 2.1 的正式组成部分,因此是实现此标准版本(或更高版本)的基类库的所有实现的一部分。

评论

5赞 Paweł Bulwan 4/5/2020
现在也在 .NET Standard 2.1 中可用
1赞 Dariusz Woźniak 11/17/2020
.NET 5.0 中也可用。
5赞 sofsntp 5/26/2021
.NET 5.0 包含在“.NET Core 2.0+”中
8赞 Christian Findlay 2/14/2019 #24

为了构建这里的答案,您可以创建一个字符串扩展方法,使其更加用户友好:

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

评论

2赞 Boris Callens 2/15/2019
假设您的段落和单词将始终在 en-US 中
4赞 AndrewWhalan 6/14/2019
若要避免强制区域性使用 en-US 的问题,请改用。return CultureInfo.CurrentCulture.CompareInfo.IndexOf(paragraph, word, CompareOptions.IgnoreCase) >= 0;
19赞 Pradeep Asanka 12/11/2019 #25

简单而有效

title.ToLower().Contains("String".ToLower())

评论

0赞 Ristogod 5/24/2021
而且它比大多数其他选项慢
5赞 Udi Y 7/13/2020 #26

与前面的答案类似(使用扩展方法),但有两个简单的 null 检查(C# 6.0 及更高版本):

public static bool ContainsIgnoreCase(this string source, string substring)
{
    return source?.IndexOf(substring ?? "", StringComparison.OrdinalIgnoreCase) >= 0;
}

如果 source 为 null,则返回 false(通过 null-propagation 运算符?.)

如果 substring 为 null,则视为空字符串并返回 true(通过 null-coalescing 运算符??)

如果需要,StringComparison 当然可以作为参数发送。

1赞 Valentin Peta 10/29/2020 #27

根据现有的答案和 Contains 方法的文档,我建议创建以下扩展,该扩展也处理极端情况:

public static class VStringExtensions 
{
    public static bool Contains(this string source, string toCheck, StringComparison comp) 
    {
        if (toCheck == null) 
        {
            throw new ArgumentNullException(nameof(toCheck));
        }

        if (source.Equals(string.Empty)) 
        {
            return false;
        }

        if (toCheck.Equals(string.Empty)) 
        {
            return true;
        }

        return source.IndexOf(toCheck, comp) >= 0;
    }
}
14赞 dashrader 1/8/2021 #28

可以使用字符串比较参数(可从 .NET Core 2.1 及更高版本获得)String.Contains 方法

public bool Contains (string value, StringComparison comparisonType);

例:

string title = "ASTRINGTOTEST";
title.Contains("string", StringComparison.InvariantCultureIgnoreCase);

评论

1赞 Surender Singh Malik 1/19/2021
是的,它在 .net Standard 2.1 和 .Net Core 5.0 learn.microsoft.com/en-us/dotnet/api/ 中可用......作为 - github.com/dotnet/runtime/issues/22198 的一部分得到修复
5赞 Ben 9/28/2021 #29

最受好评的几个答案都以自己的方式很好和正确,我写在这里是为了添加更多信息、背景和观点。

为了清楚起见,如果 A 中有任何等于 B 的代码点子序列,我们假设字符串 A 包含字符串 B。如果我们接受这一点,问题就简化为两个字符串是否相等的问题。

几十年来,人们一直在详细考虑字符串何时相等的问题。当前的大部分知识状态都封装在 SQL 排序规则中。Unicode 普通形式接近于此的适当子集。但是,除了 SQL 排序规则之外,还有更多内容。

例如,在 SQL 排序规则中,您可以

  • 严格区分二进制 - 因此不同的 Unicode 规范化形式(例如预组合或组合重音)会以不同的方式进行比较。

    例如,可以表示为(预组合)或(e与组合急性重音)。éU+00e9U+0065 U+0301

    这些是相同还是不同?

  • Unicode 规范化 - 在这种情况下,上述示例将彼此相等,但不等于 或 。Ée

  • 口音不敏感,(例如西班牙语、德语、瑞典语等文本)。在这种情况下U+0065 = U+0065 U+0301 = U+00e9 = é = e

  • 不区分大小写和重音,因此(例如西班牙语、德语、瑞典语等文本)。在这种情况下U+00e9 = U+0065 U+0301 = U+00c9 = U+0045 U+0301 = U+0049 = U+0065 = E = e = É = é

  • Kanatype 敏感或不敏感,即您可以将日本平假名和片假名视为等效或不同。这两个音节包含相同数量的字符,以(大部分)相同的方式组织和发音,但书写方式不同,用途不同。例如,片假名用于外来词或外来名,但平假名用于儿童读物、发音指南(例如红宝石)以及单词没有汉字的地方(或者作者可能不知道汉字,或者认为读者可能不知道)。

  • 全角或半角敏感 - 由于历史原因,日语编码包括某些字符的两种表示形式 - 它们以不同的大小显示。

  • 连字被认为等效与否:见 https://en.wikipedia.org/wiki/Ligature_(写作)

    是一样的还是不一样?它们具有不同的 Unicode 编码,重音字符也是如此,但与重音字符不同的是,它们看起来也不同。æae

    这给我们带来了...

  • 阿拉伯语表示形式等效性

    阿拉伯文字有一种美丽的书法文化,其中相邻字母的特定序列具有特定的表现形式。其中许多已采用Unicode标准进行编码。我不完全理解这些规则,但在我看来,它们类似于连字。

  • 其他脚本和系统:我完全不懂卡纳达语、马拉雅拉姆语、僧伽罗语、泰语、古吉拉特语、藏语,或者几乎所有没有提到的几十或几百种文字。我认为它们对程序员也有类似的问题,并且考虑到到目前为止提到的问题数量和如此少的脚本,它们可能还有程序员应该考虑的其他问题。

这让我们摆脱了“编码”杂草。

现在我们必须输入“意义”杂草。

  • 等于 ?如果不是,则等于 ?如果不是,为什么不呢?这是拼音罗马化。Beijing北京Bĕijīng北京

  • 等于 ?如果不是,为什么不呢?这是Wade-Giles的罗马化。Peking北京

  • 等于 ?如果不是,为什么不呢?BeijingPeking

你为什么要这样做?

例如,如果您想知道两个字符串(A 和 B)是否可能指代同一地理位置或同一个人,您可能需要询问:

  • 这些字符串可能是一组汉字序列的 Wade-Giles 或拼音表示吗?如果是这样,相应的集合之间是否有任何重叠?

  • 这些字符串之一可能是汉字的西里尔文转录吗?

  • 这些字符串之一可能是拼音罗马化的西里尔音译吗?

  • 这些字符串之一可能是拼音罗马化、英文名称汉化的西里尔音译吗?

显然,这些都是困难的问题,没有确切的答案,无论如何,答案可能会根据问题的目的而有所不同。

最后举一个具体的例子。

  • 如果您要递送信件或包裹,请明确 、 和 都是平等的。为此,它们都同样出色。毫无疑问,中国邮局认可许多其他选择,例如法语、葡萄牙语、越南语和蒙古语。BeijingPekingBĕijīng北京PékinPequimBắc KinhБээжин

单词没有固定的含义。

文字是我们用来驾驭世界、完成任务以及与他人交流的工具。

虽然看起来如果像 、 或 这样的词有固定的含义会有所帮助,但可悲的事实是它们没有。equalityBeijingmeaning

然而,我们似乎以某种方式混淆了。

TL;DR:如果你正在处理与现实有关的问题,在现实的所有模糊性(浑浊、不确定性、缺乏明确的界限)中,每个问题基本上都有三种可能的答案:

  • 可能
  • 可能不是
3赞 cabiste 5/25/2023 #30

好吧,我遇到了这篇文章,所以我决定对一些流行的答案进行基准测试,简而言之,JaredPar 的答案是最快的,内存分配为 0,而 Colonel Panic 的答案是最慢的

基准信息

  • 日期: 2023/05
  • .NET SDK:7.0.103.NET SDK:7.0.103.NET SDK:7.0.103.NET SDK.NET
  • 基准点网:0.13.5
  • 处理器: i3-8100
  • 操作系统: Arch Linux

使用的代码

[MemoryDiagnoser]
public class StringContains
{
    [Params("How to install Arch Linux?")]
    public string Phrase { get; set; }
    [Params("How to", "arch", "blazor", "random long string to see if it effects the time needed")]
    public string search { get; set; }

    [Benchmark(Baseline = true)]
    public bool Contains() =>
        Phrase.Contains(search, System.StringComparison.CurrentCultureIgnoreCase);

    [Benchmark]
    public bool toUpper() =>
        Phrase.ToUpper().Contains(search.ToUpper());

    [Benchmark]
    public bool toLower() =>
        Phrase.ToLower().Contains(search.ToLower());

    [Benchmark]
    public bool IndexeOf() =>
        Phrase.IndexOf(search, StringComparison.OrdinalIgnoreCase) >= 0;

    [Benchmark]
    public bool CultureCompareInfo()
    {
        var culture = new CultureInfo("en-US");
        return culture.CompareInfo.IndexOf(Phrase, search, CompareOptions.IgnoreCase) >= 0;
    }
}

结果

我删除了一些列,因为它们并不重要

方法 短语 搜索 意味 着 第 0 代 分配
包含 如何t(...)伊克斯?[26] 如何 46.887纳秒 1.00 - -
到上部 如何t(...)伊克斯?[26] 如何 88.386纳秒 1.89 0.0381 120 字节
到下 如何t(...)伊克斯?[26] 如何 87.196纳秒 1.86 0.0381 120 字节
索引 如何t(...)伊克斯?[26] 如何 19.730纳秒 0.42 - -
文化比较信息 如何t(...)伊克斯?[26] 如何 166.691纳秒 3.56 0.0560 176 字节
包含 如何t(...)伊克斯?[26] 98.794纳秒 1.00 - -
到上部 如何t(...)伊克斯?[26] 86.692纳秒 0.88 0.0356 112 字节
到下 如何t(...)伊克斯?[26] 70.534纳秒 0.71 0.0254 80 字节
索引 如何t(...)伊克斯?[26] 26.405纳秒 0.27 - -
文化比较信息 如何t(...)伊克斯?[26] 219.527纳秒 2.22 0.0560 176 字节
包含 如何t(...)伊克斯?[26] Blazor 118.889纳秒 1.00 - -
到上部 如何t(...)伊克斯?[26] Blazor 83.605纳秒 0.70 0.0381 120 字节
到下 如何t(...)伊克斯?[26] Blazor 67.559纳秒 0.57 0.0254 80 字节
索引 如何t(...)伊克斯?[26] Blazor 13.209纳秒 0.11 - -
文化比较信息 如何t(...)伊克斯?[26] Blazor 229.810纳秒 1.93 0.0560 176 字节
包含 如何t(...)伊克斯?[26] 兰多(...)伊迪德 [55] 95.442纳秒 1.00 - -
到上部 如何t(...)伊克斯?[26] 兰多(...)伊迪德 [55] 113.243纳秒 1.19 0.0688 216 字节
到下 如何t(...)伊克斯?[26] 兰多(...)伊迪德 [55] 86.116纳秒 0.90 0.0254 80 字节
索引 如何t(...)伊克斯?[26] 兰多(...)伊迪德 [55] 7.380纳秒 0.08 - -
文化比较信息 如何t(...)伊克斯?[26] 兰多(...)伊迪德 [55] 217.331纳秒 2.28 0.0560 176 字节

传说

Phrase :'Phrase' 参数的值

search :'search' 参数的值

Mean :所有测量值的算术平均值

比率:比率分布的平均值([当前]/[基线])

Gen0:GC 第 0 代每 1000 次操作收集

已分配 :每个操作分配的内存(仅托管,含,1KB = 1024B)

1 ns : 1 纳秒(0.000000001 秒)

2赞 Mohamed Salah 6/20/2023 #31

.NET 的新版本 具有忽略大小写的功能

examplestring.Contains("exampleSTRING", StringComparison.OrdinalIgnoreCase)