有没有一种方法可以实现以下返回?
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);
测试字符串段落是否包含字符串单词(谢谢@QuarterMeister)
culture.CompareInfo.IndexOf(paragraph, word, CompareOptions.IgnoreCase) >= 0
其中,culture是描述文本所用语言的CultureInfo的实例。
此解决方案对于不区分大小写的定义是透明的,这取决于语言。例如,英语在第九个字母的大写和小写版本中使用字符I和I,而土耳其语在其29个字母的长字母表中的第十一和第十二个字母中使用这些字符。土耳其大写的“i”是一个不熟悉的字符“yi”。
因此,字符串tin和tin在英语中是相同的单词,但在土耳其语中是不同的单词。据我所知,一个是“精神”,另一个是拟声词。(土耳其人,如果我错了,请纠正我,或者建议一个更好的例子)
总之,如果你知道文本是什么语言,你只能回答“这两个字符串是相同的,但在不同的情况下”这个问题。如果你不知道,你就必须接受双关语。鉴于英语在软件领域的霸主地位,你可能应该求助于CultureInfo.InvariantCulture,因为它在熟悉的方面是错误的。
如果您担心国际化(或者您可以重新实现它),VisualBasic程序集的InStr方法是最好的。看看dotNeetWeek,它不仅说明了大写字母和小写字母,还说明了假名类型和全半角字符(大多数与亚洲语言相关,尽管罗马字母表也有全半角版本)。我跳过了一些细节,但请查看私有方法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);
}
OrdinalIgnoreCase、CurrentCultureIgnoreCare或InvariantCultureIgnoleCase?
由于缺少此项,以下是关于何时使用哪项的一些建议:
Dos
使用StringComparison.OrdinalIgnoreCase进行比较作为区域性不可知字符串匹配的安全默认值。使用StringComparison.OrdinalIgnoreCase比较以提高速度。使用StringComparison.CurrentCulture-based字符串操作当向用户显示输出时。基于不变量切换字符串操作的当前使用当比较为语言上不相关(例如象征性的)。在以下情况下使用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
这与这里的其他示例非常相似,但我决定将enum简化为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) )
....
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
}
.NET Core 2.0+(包括.NET 5.0+)
自2.0版以来,.NET Core有两种方法来处理此问题:
String.Contains(Char,StringComparison)String.Contains(字符串,StringComparison)
例子:
"Test".Contains("test", System.StringComparison.CurrentCultureIgnoreCase);
它现在正式成为.NET标准2.1的一部分,因此也是实现此版本标准(或更高版本)的基类库的所有实现的一部分。
与前面的答案类似(使用扩展方法),但有两个简单的空检查(C#6.0及以上版本):
public static bool ContainsIgnoreCase(this string source, string substring)
{
return source?.IndexOf(substring ?? "", StringComparison.OrdinalIgnoreCase) >= 0;
}
如果源为空,则返回false(通过空传播运算符?)
如果子字符串为空,则将其视为空字符串并返回true(通过空合并运算符??)
如果需要,StringComparison当然可以作为参数发送。
排名靠前的几个答案都是正确的,我在这里补充了更多信息、背景和观点。
为了清楚起见,让我们考虑字符串A包含字符串B,如果A中有任何等于B的代码点子序列。如果我们接受这一点,问题就归结为两个字符串是否相等的问题。
字符串何时相等的问题已经被详细考虑了几十年。当前知识的大部分状态都封装在SQL排序规则中。Unicode正规形式接近于这一类型的适当子集。但是,除了SQL排序之外,还有更多的内容。
例如,在SQL排序规则中,可以
严格区分二进制-因此不同的Unicode规范化形式(例如预组合或组合重音)的比较不同。例如,é可以表示为U+00e9(预组合)或U+0065 U+0301(e带组合锐音符)。这些相同还是不同?Unicode规范化-在这种情况下,上述示例将彼此相等,但不等于É或e。不区分重音,(例如西班牙语、德语、瑞典语等文本)。在这种情况下,U+0065=U+0065 U+0301=U+00e9=é=e不区分大小写和重音,因此(例如西班牙语、德语、瑞典语等文本)。在这种情况下,U+00e9=U+0065 U+0301=U+000c9=U+0.045 U+0301=U+0049=U+0065=E=E=É=é假名类型敏感或不敏感,即您可以将日语平假名和片假名视为等同或不同。这两个音节包含相同数量的字符,组织和发音方式(大部分)相同,但书写方式不同,用途不同。例如,片假名用于外来词或外国名字,而平假名用于儿童读物、发音指南(例如rubies),以及单词没有汉字的地方(或者作者不知道汉字,或者认为读者可能不知道)。全宽或半宽敏感-由于历史原因,日语编码包括一些字符的两种表示形式-它们以不同的大小显示。配体是否等效:参见https://en.wikipedia.org/wiki/Ligature_(书面)æ是否与ae相同?它们有不同的Unicode编码,重音字符也是如此,但与重音字符不同,它们看起来也不同。这让我们想到。。。阿拉伯语表示形式等效阿拉伯书写有一种优美的书法文化,其中相邻字母的特定序列有特定的表示。其中许多都是用Unicode标准编码的。我不完全理解这些规则,但在我看来,它们类似于连字。其他文字和系统:我对卡纳达语、马拉雅拉姆语、僧伽罗语、泰语、古吉拉特语、藏语或几乎所有未提及的数十种或数百种文字一无所知。我假设他们对程序员也有类似的问题,考虑到目前为止提到的问题数量和脚本数量,他们可能也有程序员应该考虑的其他问题。
这让我们摆脱了“编码”杂草。
现在我们必须输入“含义”杂草。
北京等于吗北京? 如果不是,Bĕijīng是否等于北京? 如果没有,为什么不呢?这是拼音罗马化。北京等于吗北京? 如果没有,为什么不呢?这是韦德·吉尔斯的罗马化。北京等于北京吗?如果没有,为什么不呢?
你为什么要这么做?
例如,如果您想知道两个字符串(A和B)是否可能指向同一地理位置或同一个人,您可能想问:
这些字符串是Wade Giles还是一组汉字序列的拼音表示?如果是,对应的集合之间是否有重叠?这些字符串中是否有一个是汉字的西里尔字母?这些字符串中有一个是拼音罗马化的西里尔音译吗?这些字符串中是否有一个是英文名称汉语化的拼音罗马化的西里尔文音译?
很明显,这些问题很难回答,没有明确的答案,而且在任何情况下,答案可能会根据问题的目的而有所不同。
以一个具体的例子结束。
如果您正在递送信件或包裹,请明确注明北京、北京、北京和北京 都是相等的。出于这个目的,它们都是同样好的。毫无疑问,中国邮政局承认许多其他选择,如法语的Pékin、葡萄牙语的Pequim、Bắ越南语为c Kinh,蒙古语为Бээжин。
单词没有固定的含义。
语言是我们用来导航世界、完成任务以及与他人交流的工具。
虽然看起来,如果平等、北京或意义等词有固定的含义会有所帮助,但可悲的是,它们没有固定的含义。
然而,我们似乎不知怎么混过去了。
TL;DR:如果你正在处理与现实相关的问题,在所有的模糊性(模糊、不确定性、缺乏清晰的边界)中,每个问题基本上有三种可能的答案:
可能可能不会大概