Без учета регистра 'Содержит (строка)'

Есть ли способ сделать следующее возвращение верным?

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

Кажется, что нет перегрузки, которая позволяет мне устанавливать чувствительность к регистру. , В настоящее время я ОБЕСПЕЧИВАЮ их обоих, но это просто глупо (под этим я имею в виду проблемы i18n , которые идут с корпусом вверх и вниз).

ОБНОВЛЕНИЕ
Этот вопрос древний, и с тех пор я понял, что попросил простой ответ на действительно обширную и сложную тему, если вы хотите исследовать его полностью.
В большинстве случаев для одноязычного, английского кодовых баз этого ответа будет достаточно. Я подозреваю, потому что большинство людей, приходящих сюда, попадают в эту категорию, это самый популярный ответ.
Этот ответ, однако, поднимает внутреннюю проблему, заключающуюся в том, что мы не можем сравнивать текст без учета регистра, пока мы не знаем, что оба текста - это одна и та же культура, и мы не знаем, что это за культура. Это, возможно, менее популярный ответ, но я думаю, что он более правильный, и именно поэтому я отметил его как таковой.

вопрос задан 14.01.2009
Boris Callens
35072 репутация

23 ответов


  • 2393 рейтинг

    Вы можете использовать строку . 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), для более старых версий используйте

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

    ИСПОЛЬЗОВАНИЕ:

    string title = "STRING";
    bool contains = title.Contains("string", StringComparison.OrdinalIgnoreCase);
    
    ответ дан JaredPar, с репутацией 555649, 14.01.2009
  • 1118 рейтинг

    Чтобы проверить, содержит ли строка paragraph строку word (спасибо @QuarterMeister)

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

    Где culture - это экземпляр CultureInfo , описывающий язык, на котором написан текст.

    Это решение прозрачно около определения нечувствительности к регистру, которое зависит от языка . Например, английский язык использует символы I и i для прописных и строчных букв девятой буквы, тогда как турецкий язык использует эти символы для одиннадцатой и двенадцатой букв своего 29-буквенного алфавита. Турецкая версия «i» в верхнем регистре - это незнакомый символ «İ».

    Таким образом, строки tin и TIN - это одно и то же слово в английском , но разные слова в турецком . Как я понимаю, одно означает «дух», а другое - слово звукоподражания. (Турки, поправьте меня, если я ошибаюсь, или предложите лучший пример)

    Подводя итог, вы можете ответить только на вопрос «являются ли эти две строки одинаковыми, но в разных случаях» , если вы знаете, на каком языке текст в . Если вы не знаете, вам придется взять с собой пунт. Учитывая гегемонию английского языка в программном обеспечении, вам, вероятно, следует прибегнуть к CultureInfo.InvariantCulture , потому что это будет неправильно знакомыми способами.

    ответ дан Colonel Panic, с репутацией 77755, 17.03.2013
  • 205 рейтинг

    Вы можете использовать IndexOf(), как это:

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

    Так как 0 (ноль) может быть индексом, вы проверяете по -1.

    MSDN

    Начинающаяся с нуля позиция индекса значения, если эта строка найдена, или -1 если это не так. Если значением является String. Пусто, возвращаемое значение равно 0.

    ответ дан mkchandler, с репутацией 3697, 14.01.2009
  • 117 рейтинг

    Альтернативный раствор с использованием Regex:

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

    Уведомление

    Как отметил @cHao в своем комментарии, существуют сценарии, которые приведут к тому, что это решение будет возвращать неверные результаты. Убедитесь, что вы знаете, что делаете, прежде чем случайно внедрить это решение.

    ответ дан Jed, с репутацией 6453, 28.07.2010
  • 66 рейтинг

    Вы всегда можете сначала увеличить или уменьшить количество строк.

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

    Ой, только что видел этот последний бит. Сравнение без учета регистра будет *, вероятно, * будет делать то же самое, и если производительность не является проблемой, я не вижу проблем с созданием копий в верхнем регистре и их сравнением. Я мог поклясться, что однажды видел сравнение без учета регистра. , ,

    ответ дан Ed S., с репутацией 99872, 14.01.2009
  • 48 рейтинг

    Одна из проблем, связанных с ответом, заключается в том, что он выдаст исключение, если строка имеет значение 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;
    } 
    
    ответ дан FeiBao 飞豹, с репутацией 661, 7.12.2010
  • 33 рейтинг

    Класс 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;
        }
    }
    
    ответ дан Andrew, с репутацией 7530, 18.11.2010
  • 32 рейтинг

    Это чисто и просто.

    Regex.IsMatch(file, fileNamestr, RegexOptions.IgnoreCase)
    
    ответ дан takirala, с репутацией 1228, 9.11.2012
  • 24 рейтинг

    OrdinalIgnoreCase, CurrentCultureIgnoreCase или InvariantCultureIgnoreCase?

    Так как это отсутствует, вот несколько рекомендаций о том, когда использовать какой из них:

    Dos

    • Используйте 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. ком / EN-US / библиотека / ms973919. aspx

    ответ дан Fabian Bigler, с репутацией 6222, 17.06.2014
  • 12 рейтинг

    Так же, как это:

    string s="AbcdEf";
    if(s.ToLower().Contains("def"))
    {
        Console.WriteLine("yes");
    }
    
    ответ дан cdytoby, с репутацией 446, 13.07.2014
  • 10 рейтинг

    Метод 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);
    }
    
    ответ дан Casey, с репутацией 2446, 6.12.2013
  • 9 рейтинг

    Я знаю, что это не 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");
    
    ответ дан serhio, с репутацией 15349, 9.09.2011
  • 8 рейтинг

    Используйте это:

    string.Compare("string", "STRING", new System.Globalization.CultureInfo("en-US"), System.Globalization.CompareOptions.IgnoreCase);
    
    ответ дан mr.martan, с репутацией 179, 11.07.2011
  • 8 рейтинг

    В конечном итоге общая операция «содержит» сводится к такой функции,

    /// 
    /// Determines whether the source contains the sequence. ///
     
    /// The type of the items in the sequences.
    /// 
    The source enumerator.
    /// 
    The sequence enumerator.
    /// 
    An equality comparer.
    /// 
    /// An empty sequence will return true.
    /// The sequence must support 
    /// if it does not begin the source.
    /// 
    /// 
    /// true if the source contains the sequence;
    /// otherwise false.
    /// 
    public static bool Contains(
        IEnumerator sourceEnumerator,
        IEnumerator sequenceEnumerator,
        IEqualityComparer equalityComparer)
    {
        if (equalityComparer == null)
        {
            equalityComparer = EqualityComparer.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(
            this IEnumerable source,
            IEnumerable sequence,
            IEqualityComparer 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,

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

    Однако, как мы знаем, строки не являются общими, они специализированы. Есть два ключевых фактора в игре.

    1. Проблема "кожуха", которая сама по себе имеет различные зависящие от языка крайние случаи.
    2. Довольно сложный вопрос о том, как набор «Текстовые элементы» (буквы / цифры / символы и т. Д.) ) представлены кодовыми точками Unicode, и какие действительные последовательности символов могут представлять данную строку, подробности раскрыты в , эти и ответы .

    Чистый эффект тот же. Строки, которые вы можете утверждать, лингвистически равны, могут быть корректно представлены различными комбинациями символов. Более того, правила действительности меняются между культурами.

    Все это приводит к специализированной строковой реализации «Содержит», как это.

    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)
    
    ответ дан Jodrell, с репутацией 25661, 3.12.2014
  • 6 рейтинг

    Использование RegEx - прямой способ сделать это:

    Regex.IsMatch(title, "string", RegexOptions.IgnoreCase);
    
    ответ дан Stend, с репутацией 111, 18.09.2013
  • 5 рейтинг

    Это очень похоже на другой пример здесь, но я решил упростить 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) )
    ....
    
    ответ дан TarmoPikaro, с репутацией 1531, 17.10.2015
  • 3 рейтинг

    Это самые простые решения.

    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);
      
    ответ дан LAV VISHWAKARMA, с репутацией 629, 12.07.2018
  • 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);
    

    Выход «Сброс»

    ответ дан Mr.B, с репутацией 1602, 3.05.2016
  • 2 рейтинг

    Вы можете использовать функцию string.indexof (). Это будет без учета регистра

    ответ дан Okan SARICA, с репутацией 77, 11.12.2016
  • 2 рейтинг
    if ("strcmpstring1".IndexOf(Convert.ToString("strcmpstring2"), StringComparison.CurrentCultureIgnoreCase) >= 0){return true;}else{return false;}
    
    ответ дан Tamilselvan K, с репутацией 420, 26.10.2016
  • 0 рейтинг
    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;
        }
    
        /// 
    /// 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. ///
     
        /// 
        /// The string to search inside.
        /// 
        /// 
        /// The string to seek.
        /// 
        /// 
        /// 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.
        /// 
        /// 
        /// fullText or value is null.
        /// 
        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
    }
    
    ответ дан Final Heaven, с репутацией 41, 14.06.2017
  • 0 рейтинг

    Если вы хотите проверить, находится ли переданная вами строка в строке, для этого есть простой метод.

    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
    
    ответ дан shaishav shukla, с репутацией 118, 16.11.2017
  • -3 рейтинг

    Простой способ для новичка:

    title.ToLower().Contains("string");//of course "string" is lowercase.
    
    ответ дан O Thạnh Ldt, с репутацией 53, 17.04.2017