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

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

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

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

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

14.01.2009 21:39:46
25 ОТВЕТОВ
РЕШЕНИЕ

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

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

Где cultureэто пример CultureInfoописания языка, на котором написан текст.

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

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

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

1379
10.08.2017 12:06:38
Почему нет culture.CompareInfo.IndexOf(paragraph, word, CompareOptions.IgnoreCase) >= 0? Он использует правильную культуру и нечувствителен к регистру, он не выделяет временные строчные буквы, и он избегает вопроса о том, всегда ли преобразование в строчные буквы и сравнение всегда то же самое, что и сравнение без учета регистра.
Quartermeister 18.03.2013 15:32:39
Это решение также излишне загрязняет кучу, выделяя память для того, что должно быть функцией поиска
JaredPar 18.03.2013 16:09:38
Сравнение с ToLower () даст отличные результаты от нечувствительного к регистру IndexOf, когда две разные буквы имеют одинаковую строчную букву. Например, вызов ToLower () для U + 0398 «Греческая заглавная буква тета» или U + 03F4 «Греческая заглавная буква тета» приводит к U + 03B8, «Греческая строчная буква тета», но заглавные буквы считаются разными. Оба решения рассматривают строчные буквы с одинаковыми заглавными буквами по-разному, например, U + 0073 «Латинская строчная буква S» и U + 017F «Латинская строчная буква Long S», поэтому решение IndexOf выглядит более согласованным.
Quartermeister 18.03.2013 17:47:27
@Quartermeister - и, кстати, я считаю, что .NET 2 и .NET4 ведут себя по-разному, так как .NET 4 всегда использует NORM_LINGUISTIC_CASING, а .NET 2 - нет (этот флаг появился в Windows Vista).
Simon Mourier 23.03.2013 08:13:06
Почему вы не написали "ddddfg" .IndexOf ("Df", StringComparison.OrdinalIgnoreCase)?
Chen 23.08.2015 13:41:49

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

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

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

79
14.01.2009 21:54:21
Ищите «Тест Турции» :)
Jon Skeet 14.01.2009 21:48:30
В некоторых французских локалях заглавные буквы не имеют диакритических знаков, поэтому ToUpper () может быть не лучше ToLower (). Я бы сказал, использовать соответствующие инструменты, если они доступны - сравнение без учета регистра.
Blair Conrad 14.01.2009 22:03:59
Не используйте ToUpper или ToLower, и делайте то, что сказал Джон Скит
Peter Gfader 21.08.2009 02:49:03
Просто увидел это снова после двух лет и нового понижения ... во всяком случае, я согласен, что есть лучшие способы для сравнения строк. Однако не все программы будут локализованы (большинство не будет), и многие из них являются внутренними или одноразовыми приложениями. Так как я вряд ли могу рассчитывать на кредит за лучший совет для одноразовых приложений ... Я перехожу: D
Ed S. 25.01.2011 07:28:26
Поиск в "Тесте Турции" - это то же самое, что и в поиске "TURKEY TEST"?
JackAce 1.06.2018 16:24:05

Вы можете использовать метод 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);
2698
8.05.2018 12:57:07
Отличный метод расширения строки! Я отредактировал мой, чтобы проверить, что исходная строка не пуста, чтобы предотвратить возникновение ошибок ссылки на объект при выполнении .IndexOf ().
Richard Pursehouse 8.02.2013 10:48:45
Это дает тот же ответ, что и paragraph.ToLower(culture).Contains(word.ToLower(culture))с, CultureInfo.InvariantCultureи не решает никаких проблем локализации. Зачем усложнять вещи? stackoverflow.com/a/15464440/284795
Colonel Panic 17.03.2013 18:52:43
@ColonelPanic ToLowerверсия включает в себя 2 выделения, которые не нужны в операции сравнения / поиска. Зачем ненужно выделять в сценарии, который этого не требует?
JaredPar 18.03.2013 16:09:08
@ Seabiscuit, который не будет работать, потому stringчто, IEnumerable<char>следовательно, вы не можете использовать его для поиска подстрок
JaredPar 6.11.2014 17:55:52
Предупреждение: по умолчанию string.IndexOf(string)используется текущая культура, а по умолчанию string.Contains(string)используется порядковый компаратор. Как мы знаем, первое можно изменить, выбрав более длительную перегрузку, а второе нельзя изменить. Следствием этого несоответствия является следующий пример кода:Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture; string self = "Waldstrasse"; string value = "straße"; Console.WriteLine(self.Contains(value));/* False */ Console.WriteLine(self.IndexOf(value) >= 0);/* True */
Jeppe Stig Nielsen 18.02.2016 09:40:37

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

230
15.09.2015 15:45:31

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

bool contains = Regex.IsMatch("StRiNG to search", Regex.Escape("string"), RegexOptions.IgnoreCase);
146
17.12.2018 09:18:03
Хорошая идея, также у нас есть много побитовых комбинаций в RegexOptions, как RegexOptions.IgnoreCase & RegexOptions.IgnorePatternWhitespace & RegexOptions.CultureInvariant;для любого, если это поможет.
Saravanan 24.08.2011 04:36:30
Должен сказать, что я предпочитаю этот метод, хотя и использую IsMatch для аккуратности.
wonea 7.09.2011 17:40:01
Что еще хуже, поскольку строка поиска интерпретируется как регулярное выражение, ряд знаков препинания приведет к неверным результатам (или вызовет исключение из-за недопустимого выражения). Попробуйте поискать "."в "This is a sample string that doesn't contain the search string". Или попробуйте поискать "(invalid", в этом отношении.
cHao 9.09.2011 13:28:56
@cHao: в этом случае, Regex.Escapeможет помочь. Регулярное выражение все еще кажется ненужным, когда IndexOf/ extension Containsпростое (и, возможно, более понятное).
Dan Mangiarelli 9.09.2011 16:44:22
Обратите внимание, что я не имел в виду, что это решение Regex было лучшим способом. Я просто добавлял в список ответов на исходный вопрос «Есть ли способ сделать следующее возвращение верным?».
Jed 13.09.2011 15:43:25

Класс 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
25.01.2011 06:58:32
почему вы позволяете ДРУГОЙ слой абстракции StringComparison?
l--''''''---------'''''''''''' 20.06.2019 18:37:30

Одна из проблем с ответом состоит в том, что он выдаст исключение, если строка имеет значение 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;
} 
52
5.06.2015 06:02:45
Если toCheck - пустая строка, она должна возвращать true в соответствии с документацией Contains: "true, если параметр value встречается в этой строке или значение является пустой строкой (" "); в противном случае - false."
amurra 16.02.2011 16:13:42
Основываясь на комментарии Амурры выше, нужно ли исправлять предложенный код? И не следует ли добавить это к принятому ответу, чтобы лучший ответ был первым?
David White 30.08.2011 03:43:38
Теперь это вернет true, если source является пустой строкой или null, независимо от того, что является toCheck. Это не может быть правильным. Также IndexOf уже возвращает true, если toCheck является пустой строкой, а source не равен null. Здесь нужна проверка на ноль. Я предлагаю, чтобы (source == null || value == null) вернул false;
Colin 1.07.2013 12:21:20
Источник не может быть нулевым
Lucas 14.12.2016 16:55:26
if (string.IsNullOrEmpty(source)) return string.IsNullOrEmpty(toCheck);
Kyle Delaney 4.04.2018 13:39:04

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

string.Compare("string", "STRING", new System.Globalization.CultureInfo("en-US"), System.Globalization.CompareOptions.IgnoreCase);
8
8.07.2013 08:10:58
Спрашивающий ищет Containsне Compare.
DuckMaestro 11.07.2011 08:05:29
@DuckMaestro, принятый ответ реализуется Containsс помощью IndexOf. Так что этот подход одинаково полезен! Пример кода C # на этой странице использует string.Compare (). Выбор команды SharePoint это!
vulcan raven 5.01.2013 10:07:01

Я знаю, что это не 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");
11
9.09.2011 13:55:07

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

Regex.IsMatch(file, fileNamestr, RegexOptions.IgnoreCase)
35
6.06.2018 14:54:20
Это будет соответствовать шаблону, хотя. В вашем примере, если fileNamestrесть какие - либо специальные символы регулярных выражений (например *, +, .и т.д.) , то вы будете в течение довольно неожиданно. Единственный способ заставить это решение работать как правильная Containsфункция - это уйти fileNamestrот дел Regex.Escape(fileNamestr).
XåpplI'-I0llwlg'I - 3.02.2013 15:18:36
кроме того, разбор и сопоставление регулярных выражений намного более ресурсоемки, чем простое сравнение без
phuclv 30.11.2019 05:51:21

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

Regex.IsMatch(title, "string", RegexOptions.IgnoreCase);
6
19.07.2016 19:23:19
Ваш ответ точно такой же, как у guptat59, но, как было указано в его ответе, он будет соответствовать регулярному выражению, поэтому, если тестируемая строка содержит какие-либо специальные символы регулярного выражения, она не даст желаемого результата.
Casey 9.12.2013 22:55:24
Это прямая копия этого ответа и страдает от тех же проблем, которые отмечены в этом ответе
Liam 10.10.2016 10:04:01
Согласовано. Изучите регулярные выражения
Jared 26.12.2017 05:14:32

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);
}
11
6.12.2013 14:11:23

OrdinalIgnoreCase, CurrentCultureIgnoreCase или InvariantCultureIgnoreCase?

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

ДОС

  • Используйте 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

27
23.07.2015 10:30:30
Что делать, если вы знаете, что вы всегда получите английскую строку. какой использовать?
BKSpurgeon 23.03.2017 23:43:53
@BKSpurgeon Я бы использовал OrdinalIgnoreCase, если случай не имеет значения
Fabian Bigler 24.03.2017 08:09:08

Именно так:

string s="AbcdEf";
if(s.ToLower().Contains("def"))
{
    Console.WriteLine("yes");
}
11
19.07.2016 19:23:43
Это не зависит от культуры и может не сработать в некоторых случаях. culture.CompareInfo.IndexOf (абзац, слово, CompareOptions.IgnoreCase).
hikalkan 22.07.2014 07:50:47
Зачем избегать string.ToLower () при сравнении строк без учета регистра? Tl; Dr Это дорого, потому что новая строка "изготовлена".
Liam 10.10.2016 10:00:29

Это очень похоже на другой пример здесь, но я решил упростить 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) )
....
5
17.10.2015 07:46:58

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

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

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

2
31.10.2017 15:16:18
if ("strcmpstring1".IndexOf(Convert.ToString("strcmpstring2"), StringComparison.CurrentCultureIgnoreCase) >= 0){return true;}else{return false;}
2
26.10.2016 14:34:14

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

2
11.12.2016 13:41:20

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

title.ToLower().Contains("string");//of course "string" is lowercase.
-4
23.03.2018 03:33:44
Даунвот за то, что просто неверен Что если title = StRiNg? StRiNg! = Строка и StRiNg! = STRING
berniefitz 21.10.2017 04:30:54
Я был неправ. Отредактируйте ответ следующим образом, слишком просто: <br/> title.ToLower (). Contains ("string") // конечно "string" в нижнем регистре
O Thạnh Ldt 23.03.2018 03:28:07
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
}
-1
14.06.2017 03:16:07

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

string yourStringForCheck= "abc";
string stringInWhichWeCheck= "Test abc abc";

bool isContained = stringInWhichWeCheck.ToLower().IndexOf(yourStringForCheck.ToLower()) > -1;

Это логическое значение вернется, если строка содержится или нет

3
12.10.2019 08:00:55

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

  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.IsMatch(title, "string", RegexOptions.IgnoreCase);
20
12.07.2018 09:25:53

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

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

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

Пример:

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

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

52
8.11.2018 14:49:03
Теперь доступно также в .NET Standard 2.1
Paweł Bulwan 5.04.2020 11:32:16

Просто, чтобы развить ответ здесь, вы можете создать метод расширения строки, чтобы сделать его немного более удобным для пользователя:

    public static bool ContainsIgnoreCase(this string paragraph, string word)
    {
        return CultureInfo.CurrentCulture.CompareInfo.IndexOf(paragraph, word, CompareOptions.IgnoreCase) >= 0;
    }
5
22.09.2019 04:42:04
Предполагая, что ваш абзац и слово всегда будут в en-US
Boris Callens 15.02.2019 13:42:59
Чтобы избежать проблем с навязыванием культуры en-US, используйте return CultureInfo.CurrentCulture.CompareInfo.IndexOf(paragraph, word, CompareOptions.IgnoreCase) >= 0;вместо этого.
AndrewWhalan 13.06.2019 21:42:44

Как просто и работает

title.ToLower().Contains("String".ToLower())
3
10.12.2019 22:32:51