有没有办法让以下返回true?
string title = "ASTRINGTOTEST"; title.Contains("string");
似乎没有一个过载允许我设置区分大小写.目前我大写它们两个,但这只是愚蠢(我指的是上下套管的i18n问题).
更新
这个问题是古老的,从那时起我就意识到,如果你想完全研究它,我会要求一个简单的答案来解决一个非常庞大和困难的话题.
对于大多数情况,在单语言的英语代码库中,这个答案就足够了.我怀疑是因为大多数人来到这个类别这是最受欢迎的答案.然而,
这个答案提出了一个固有的问题,即我们无法比较文本不区分大小写,直到我们知道两个文本是相同的文化并且我们知道文化是什么.这可能是一个不太受欢迎的答案,但我认为它更正确,这就是为什么我这样标记它.
您可以使用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);
测试字符串是否paragraph
包含字符串word
(感谢@QuarterMeister)
culture.CompareInfo.IndexOf(paragraph, word, CompareOptions.IgnoreCase) >= 0
描述文本所用语言culture
的实例在哪里CultureInfo
.
这种解决方案对于不区分大小写的定义是透明的,这种定义与语言有关.例如,英语使用字符I
和i
第九个字母的大写和小写版本,而土耳其语使用这些字符作为其29个字母长字母的第11和第12个字母.土耳其大写版本的'i'是不熟悉的角色'İ'.
因此,串tin
并TIN
是同一个词在英语,但不同的词在土耳其.据我所知,一个是"精神",另一个是拟声词.(土耳其人,请纠正我,如果我错了,或建议一个更好的例子)
总而言之,如果您知道文本所使用的语言,则只能回答"这两个字符串是否相同但在不同情况下" 的问题.如果你不知道,你将不得不采取行动.鉴于英语在软件方面的霸权,你应该诉诸于此CultureInfo.InvariantCulture
,因为以熟悉的方式会出错.
你可以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.
使用Regex的替代解决方案:
bool contains = Regex.IsMatch("StRiNG to search", Regex.Escape("string"), RegexOptions.IgnoreCase);
您可以先将字符串向上或向下放大.
string title = "string": title.ToUpper().Contains("STRING") // returns true
哎呀,刚看到最后一点.不区分大小写的比较可能*
会*
做同样的事情,如果性能不是问题,我没有看到创建大写副本和比较它们的问题.我曾经发誓我曾经看过一次不区分大小写的比较...
答案的一个问题是,如果字符串为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; }
这很简洁.
Regex.IsMatch(file, fileNamestr, RegexOptions.IgnoreCase)
从2.0版开始,.NET Core有一对处理这个问题的方法:
String.Contains(Char,StringComparison)
String.Contains(String,StringComparison)
例:
"Test".Contains("test", System.StringComparison.CurrentCultureIgnoreCase);
随着时间的推移,他们可能会进入.NET标准,并从那里进入基类库的所有其他实现.
StringExtension类是前进的方法,我结合上面的几个帖子给出了一个完整的代码示例:
public static class StringExtensions { ////// Allows case insensitive checks /// public static bool Contains(this string source, string toCheck, StringComparison comp) { return source.IndexOf(toCheck, comp) >= 0; } }
OrdinalIgnoreCase,CurrentCultureIgnoreCase还是InvariantCultureIgnoreCase?
由于缺少这个,这里有一些关于何时使用哪一个的建议:
使用StringComparison.OrdinalIgnoreCase
的比较作为默认的安全文化无关的字符串匹配.
使用StringComparison.OrdinalIgnoreCase
比较来提高速度.
StringComparison.CurrentCulture-based
向用户显示输出时使用字符串操作.
切换基于不变文化的字符串操作的当前使用以使用非语言StringComparison.Ordinal
或 StringComparison.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
这些是最简单的解决方案.
按索引
string title = "STRING"; if (title.IndexOf("string", 0, StringComparison.CurrentCultureIgnoreCase) != -1) { // contains }
通过改变案例
string title = "STRING"; bool contains = title.ToLower().Contains("string")
通过Regex
Regex.IsMatch(title, "string", RegexOptions.IgnoreCase);
我知道这不是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");
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); }
像这样:
string s="AbcdEf"; if(s.ToLower().Contains("def")) { Console.WriteLine("yes"); }
用这个:
string.Compare("string", "STRING", new System.Globalization.CultureInfo("en-US"), System.Globalization.CompareOptions.IgnoreCase);
使用RegEx是一种直接的方法:
Regex.IsMatch(title, "string", RegexOptions.IgnoreCase);
这与此处的其他示例非常相似,但我决定将枚举简化为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) ) ....