Без учета регистра 'Содержит (строка)' - PullRequest
2671 голосов
/ 15 января 2009

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

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

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

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

Ответы [ 24 ]

2539 голосов
/ 15 января 2009

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

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

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

string title = "STRING";
bool contains = title.Contains("string", StringComparison.OrdinalIgnoreCase);
1248 голосов
/ 17 марта 2013

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

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

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

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

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

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

216 голосов
/ 15 января 2009

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

string title = "STRING";

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

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

* MSDN 1008 *

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

130 голосов
/ 28 июля 2010

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

bool contains = Regex.IsMatch("StRiNG to search", Regex.Escape("string"), RegexOptions.IgnoreCase);
74 голосов
/ 15 января 2009

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

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

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

50 голосов
/ 08 декабря 2010

Одна из проблем с ответом состоит в том, что он выдаст исключение, если строка имеет значение 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;
} 
35 голосов
/ 18 ноября 2010

Класс 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;
    }
}
35 голосов
/ 09 ноября 2012

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

Regex.IsMatch(file, fileNamestr, RegexOptions.IgnoreCase)
24 голосов
/ 17 июня 2014

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.com/en-us/library/ms973919.aspx

17 голосов
/ 13 октября 2018

.NET Core 2.0+ только (на данный момент)

.NET Core имеет пару методов для решения этой проблемы начиная с версии 2.0:

  • String.Contains (Char, StringComparison )
  • String.Contains (String, StringComparison )

Пример:

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

Со временем они, вероятно, перейдут в стандарт .NET и оттуда во все другие реализации библиотеки базовых классов.

...