首页 文章

不区分大小写'Contains(string)'

提问于
浏览
2533

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

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

没有什么是愚蠢的(我指的是上下套管带来的i18n问题) .

UPDATE
这个问题是古老的,从那时起我就意识到,如果你想完全研究它,我会要求一个简单的答案来解决一个非常庞大而困难的话题 .
对于大多数情况,在单语言的英语代码库中,答案就足够了 . 我怀疑是因为大多数人来到这个类别这是最受欢迎的答案 .
然而,This答案提出了我们可以如此标记的固有问题 .

24 回答

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

    输出是“重置”

  • 118

    这很简洁 .

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

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

    string yourStringForCheck= "abc";
    string stringInWhichWeCheck= "Test abc abc";
    
    bool isContaines = stringInWhichWeCheck.ToLower().IndexOf(yourStringForCheck.ToLower()) > -1;
    
    This boolean value will return if string contains or not
    
  • 67

    这与此处的其他示例非常相似,但我决定将枚举简化为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) )
    ....
    
  • 48
    if ("strcmpstring1".IndexOf(Convert.ToString("strcmpstring2"), StringComparison.CurrentCultureIgnoreCase) >= 0){return true;}else{return false;}
    
  • 2437

    .NET Core 2.0(截至目前)

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

    • String.Contains(Char, StringComparison

    • String.Contains(String, StringComparison

    例:

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

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

  • 10

    您可以使用String.IndexOf Method并传递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 propagation ?. 可供旧版本使用

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

    用法:

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

    如果您对国际化有所顾虑(或者您可以重新实现),那么VisualBasic程序集中的 InStr 方法是最好的 . 在它看来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);
    }
    
  • 5

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

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

    哎呀,刚看到最后一点 . 不区分大小写的比较 * 可能 * 无论如何也是如此,如果性能不是问题,我认为创建大写副本并比较它们没有问题 . 我曾经发誓我曾经看过一次不区分大小写的比较...

  • 2

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

    您可以使用 string.indexof () 功能 . 这将不区分大小写

  • 6

    使用Regex的替代解决方案:

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

    Notice

    正如@cHao在他的评论中指出的那样,有一些情况会导致这个解决方案返回错误的结果 . 在随意实施此解决方案之前,请确保您知道自己在做什么 .

  • 2

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

    用这个:

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

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

    • 按索引
    string title = "STRING";
    
    if (title.IndexOf("string", 0, StringComparison.CurrentCultureIgnoreCase) != -1)
    {
        // contains 
    }
    
    • 通过改变案例
    string title = "STRING";
    
    bool contains = title.ToLower().Contains("string")
    
    • By Regex
    Regex.IsMatch(title, "string", RegexOptions.IgnoreCase);
    
  • 34

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

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

    其中 cultureCultureInfo的实例,描述了写入文本的语言 .

    该解决方案对于 the definition of case-insensitivity, which is language dependent 是透明的 . 例如,英语使用字符 Ii 作为第九个字母的大写和小写版本,而土耳其语使用这些字符作为其29个字母长字母的eleventh and twelfth letters . 'i'的土耳其大写版本是不熟悉的字符'İ' .

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

    总而言之,如果您知道该文本所使用的语言,则只能回答问题'are these two strings the same but in different cases' . 如果您不愿意采取行动 . 鉴于英语在软件方面的霸权,你应该诉诸于CultureInfo.InvariantCulture,因为以熟悉的方式会出错 .

  • 33

    新手的简单方法:

    title.ToLower().Contains("string");//of course "string" is lowercase.
    
  • 6
    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
    }
    
  • 0

    最终,通用的“包含”操作归结为这样的函数,

    /// <summary>
    /// Determines whether the source contains the sequence.
    /// </summary>
    /// <typeparam name="T">The type of the items in the sequences.</typeparam>
    /// <param name="sourceEnumerator">The source enumerator.</param>
    /// <param name="sequenceEnumerator">The sequence enumerator.</param>
    /// <param name="equalityComparer">An equality comparer.</param>
    /// <remarks>
    /// An empty sequence will return <c>true</c>.
    /// The sequence must support <see cref="IEnumerator.Reset"/>
    /// if it does not begin the source.
    /// </remarks>
    /// <returns>
    /// <c>true</c> if the source contains the sequence;
    /// otherwise <c>false</c>.
    /// </returns>
    public static bool Contains<T>(
        IEnumerator<T> sourceEnumerator,
        IEnumerator<T> sequenceEnumerator,
        IEqualityComparer<T> equalityComparer)
    {
        if (equalityComparer == null)
        {
            equalityComparer = EqualityComparer<T>.Default;
        }
    
        while (sequenceEnumerator.MoveNext())
        {
            if (sourceEnumerator.MoveNext())
            {
                if (!equalityComparer.Equals(
                    sourceEnumerator.Current,
                    sequenceEnumerator.Current))
                {
                    sequenceEnumerator.Reset();
                }
            }
            else
            {
                return false;
            }
        }
    
        return true;
    }
    

    这可以简单地包含在接受 IEnumerable 这样的扩展版本中,

    public static bool Contains<T>(
            this IEnumerable<T> source,
            IEnumerable<T> sequence,
            IEqualityComparer<T> equalityComparer = null)
    {
        if (sequence == null)
        {
            throw new ArgumentNullException("sequence");
        }
    
        using(var sequenceEnumerator = sequence.GetEnumerator())
        using(var sourceEnumerator = source.GetEnumerator())
        {
            return Contains(
                sourceEnumerator,
                sequenceEnumerator,
                equalityComparer);
        }
    }
    

    现在,这将适用于序数比较任何序列,包括字符串,因为 string 实现 IEnumerable<char>

    // The optional parameter ensures the generic overload is invoked
    // not the string.Contains() implementation.
    "testable".Contains("est", EqualityComparer<char>.Default)
    

    但是,正如我们所知,字符串不是通用的,它们是专门的 . 有两个关键因素在起作用 .

    • "casing"问题本身有各种语言相关的边缘情况 .

    • 如果一组"Text Elements"(字母/数字/符号等)由Unicode代码点表示以及哪些有效的字符序列可以表示给定字符串,则涉及的问题在these answers中进行了扩展 .

    净效果是一样的 . 您可能声称在语言上相等的字符串可以通过不同的字符组合有效地表示 . 更重要的是,有效性规则在不同文化之间发生变化 .

    所有这些都导致了一个基于特殊字符串的“包含”实现 .

    using System.Globalization;
    
    public static bool Contains(
             this string source,
             string value,
             CultureInfo culture = null,
             CompareOptions options = CompareOptions.None)
    {
        if (value == null)
        {
            throw new ArgumentNullException("value");
        }
    
        var compareInfo = culture == null ? 
                CultureInfo.CurrentCulture.CompareInfo :
                culture.CompareInfo;
    
        var sourceEnumerator = StringInfo.GetTextElementEnumerator(source);
        var sequenceEnumerator = StringInfo.GetTextElementEnumerator(value);
    
        while (sequenceEnumerator.MoveNext())
        {
            if (sourceEnumerator.MoveNext())
            {
                if (!(compareInfo.Compare(
                        sourceEnumerator.Current,
                        sequenceEnumerator.Current,
                        options) == 0))
                {
                    sequenceEnumerator.Reset();
                }
            }
            else
            {
                return false;
            }
        }
    
        return true;
    }
    

    无论字符串的规范化如何,此函数都可用于执行不区分大小写,特定于文化的“包含” . 例如

    "testable".Contains("EST", StringComparer.CurrentCultureIgnoreCase)
    
  • 209

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

  • -4

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

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

    OrdinalIgnoreCase, CurrentCultureIgnoreCase or 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

  • 9

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

    像这样:

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

相关问题