Нечувствительный к регистру «Содержит (строка)»

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

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

Кажется, что нет перегрузки, которая позволяет мне установить чувствительность к регистру. В настоящее время я ВЕРХНИЙ их обоих, но это просто глупо (я имею в виду проблемы i18n, которые поставляются с корпусом вверх и вниз).

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

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

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

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

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

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

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

Вы можете использовать метод 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); 

Вы можете использовать IndexOf() следующим образом:

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

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

MSDN

Значение индекса, основанного на нулевом значении, если эта строка найдена, или -1, если это не так. Если значением является String.Empty, возвращаемое значение равно 0.

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

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

уведомление

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

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

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

Класс 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; } } 

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

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

OrdinalIgnoreCase, CurrentCultureIgnoreCase или InvariantCultureIgnoreCase?

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

ДОС

  • Используйте StringComparison.OrdinalIgnoreCase для сравнения в качестве безопасного по умолчанию для сопоставления с 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 s="AbcdEf"; if(s.ToLower().Contains("def")) { Console.WriteLine("yes"); } 

Метод InStr из сборки VisualBasic является лучшим, если вы беспокоитесь о интернационализации (или вы можете переопределить его). Глядя на него, dotNeetPeek показывает, что он не только учитывает кепки и строчные буквы, но также и для типа kana и полных символов полуширины (в основном это относится к азиатским языкам, хотя также имеются полноразмерные версии латинского алфавита ). Я просматриваю некоторые детали, но проверяю частный метод 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); } 

Я знаю, что это не 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"); 

Использовать это:

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

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

 ///  /// 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. Скорее всего, вопрос о том, как набор «текстовых элементов» (буквы / цифры / символы и т. Д.) Представлены кодами Юникода и какие действительные последовательности символов могут представлять заданную строку, в этих ответах подробно раскрываются детали.

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

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

 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) 

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

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

Это довольно похоже на другой пример здесь, но я решил упростить перечисление для 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) ) .... 
 if ("strcmpstring1".IndexOf(Convert.ToString("strcmpstring2"), StringComparison.CurrentCultureIgnoreCase) >= 0){return true;}else{return false;} 

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

Хитрость здесь заключается в том, чтобы искать строку, игнорируя случай, но держать ее в точности одинаковой (с тем же случаем).

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

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

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

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

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

 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 

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

 title.ToLower().Contains("string");//of course "string" is lowercase. 
  • Две разные «строки» - это один и тот же экземпляр объекта?
  • Преобразование строки Hex в ASCII в Java
  • Получить строку между двумя строками в строке
  • Как удалить все неабелевые числовые символы из строки в MySQL?
  • Есть ли способ создать строку из массива utf16 в swift?
  • Объявления загружаются, но не отображаются?
  • Замените «\\» на «\» в строке в C #
  • Что такое @ перед строкой в ​​C #?
  • Как определить, не определена ли строка в сценарии оболочки bash?
  • string.Format (), дающий «входная строка не в правильном формате»
  • Способ иметь String.Replace только ударить "целые слова"
  • Давайте будем гением компьютера.