大文字と小文字を区別しない 'Contains(string)'


2908

次のリターンをtrueにする方法はありますか?

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

大文字と小文字の区別を設定するための過負荷はないようです。現在は両方を大文字にしていますが、それはばかげています(大文字と小文字の大文字と小文字に関連するi18nの問題を参照しています)。

更新
この質問は古くからあり、それ以来、私はあなたがそれを完全に調査することを気にかけている場合、本当に広範で困難なトピックに対して簡単な答えを求めていることに気付きました。
ほとんどの場合、単一言語の英語のコードベースでは、この回答で十分です。ここに来るほとんどの人がこのカテゴリーに該当するので、これが最も人気のある答えだと思います。ただし、
この答えは、両方のテキストが同じ文化であり、その文化が何であるかがわかるまで、大文字と小文字を区別せずにテキストを比較できないという固有の問題を引き起こします。これはあまり人気のない答えかもしれませんが、私はそれがより正しいと思うので、そのようにマークしました。

回答:


1398

文字列に文字列paragraphが含まれているかどうかをテストするにはword(@QuarterMeisterに感謝)

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

テキストが書かれている言語を説明cultureするインスタンスはどこにありますかCultureInfo

このソリューションは、言語に依存する大文字と小文字を区別しない定義については透過です。例えば、英語の文字を使用Iし、iトルコ語は、のためにこれらの文字を使用するのに対し、第九の文字の大文字と小文字バージョン用第十一及び第十二の手紙その29文字の長アルファベット。トルコ語の大文字バージョンの「i」は、なじみのない文字「İ」です。

したがって、文字列tinand TIN英語では同じ単語です、トルコでは別の単語です。私が理解しているように、1つは「精神」を意味し、もう1つは擬音語です。(タークス、私が間違っている場合は修正してください。またはより良い例を提案してください)

要約すると、テキストの言語がわかっている場合にのみ、「これらの2つの文字列は同じですが、異なる場合」という質問に答えることができます。あなたが知らなければ、パントを取る必要があります。ソフトウェアにおける英語の覇権を考えるとCultureInfo.InvariantCulture、慣れ親しんだ方法で間違っているため、おそらくに頼る必要があります。


67
なんでculture.CompareInfo.IndexOf(paragraph, word, CompareOptions.IgnoreCase) >= 0?これは適切なカルチャを使用し、大文字と小文字を区別しません。一時的な小文字の文字列を割り当てません。また、小文字への変換と比較が常に大文字と小文字を区別しない比較と同じであるかどうかの質問を回避します。
Quartermeister 2013年

9
このソリューションは、検索機能となるものにメモリを割り当てることにより、ヒープを不必要に汚染します
JaredPar

15
ToLower()と比較すると、2つの異なる文字が同じ小文字である場合に、大文字と小文字を区別しないIndexOfから異なる結果が得られます。たとえば、U + 0398 "Greek Capital Letter Theta"またはU + 03F4 "Greek Capital Letter Theta Symbol"でToLower()を呼び出すと、U + 03B8、 "Greek Small Letter Theta"になりますが、大文字は異なると見なされます。どちらのソリューションも、同じ大文字が異なる小文字(U + 0073 "Latin Small Letter S"やU + 017F "Latin Small Letter Long S"など)を考慮しているため、IndexOfソリューションはより一貫しているように見えます。
Quartermeister 2013年

3
@Quartermeister-ところで、.NET 2は常にNORM_LINGUISTIC_CASINGを使用するため、.NET 2は常にNORM_LINGUISTIC_CASINGを使用するため(。
Simon Mourier 2013年

10
なぜ "ddddfg" .IndexOf( "Df"、StringComparison.OrdinalIgnoreCase)を書かなかったのですか?

2713

String.IndexOfメソッドを使用して、使用するStringComparison.OrdinalIgnoreCase検索のタイプ​​として渡すことができます。

string title = "STRING";
bool contains = title.IndexOf("string", StringComparison.OrdinalIgnoreCase) >= 0;

さらに良いのは、stringの新しい拡張メソッドを定義することです。

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伝播 ?.が使用できることに注意してください。

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

使用法:

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

3
素晴らしい文字列拡張メソッド!.IndexOf()の実行時にオブジェクト参照エラーが発生しないように、ソース文字列がnullではないことを確認するように私のものを編集しました。
Richard Pursehouse、2013

8
これは、同じ答えを与えるparagraph.ToLower(culture).Contains(word.ToLower(culture))CultureInfo.InvariantCulture、それがどのローカライズの問題を解決していません。なぜ複雑すぎるのか?stackoverflow.com/a/15464440/284795
大佐パニック

60
@ColonelPanic ToLowerバージョンには、比較/検索操作では不要な2つの割り当てが含まれています。なぜそれを必要としないシナリオで不必要に割り当てるのですか?
JaredPar 2013年

4
@Seabiscuit stringは、IEnumerable<char>それが原因で機能しないため、サブストリングを検索するために使用できません
JaredPar

6
警告:デフォルトの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 */
ジャップスティーグニールセン

231

次の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です。


148

正規表現を使用した代替ソリューション:

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

6
良いアイデアです。また、RegexOptionsにRegexOptions.IgnoreCase & RegexOptions.IgnorePatternWhitespace & RegexOptions.CultureInvariant;は、役立つ場合は誰にとっても多くのビットごとの組み合わせがあります。
サラバナン2011

7
整然としてIsMatchを使用していますが、私はこの方法を好むと言わなければなりません。
11

31
さらに悪いことに、検索文字列は正規表現として解釈されるため、句読点文字の数が多いと不正な結果が発生します(または無効な式による例外がトリガーされます)。で検索し"."てみてください"This is a sample string that doesn't contain the search string"。または"(invalid"、を検索してみてください。
cHao

17
@cHao:その場合、Regex.Escape助けになるでしょう。IndexOf/拡張子Containsが単純な場合(そして間違いなくより明確な場合)に、Regexは依然として不要のようです。
Dan Mangiarelli、2011

6
このRegexソリューションが最善の方法であることを示唆していないことに注意してください。私は、元の投稿された質問「次のリターンをtrueにする方法はありますか?」に対する回答のリストに単に追加していました。
Jed

79

あなたはいつも最初に文字列を単に大文字または小文字にすることができます。

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

おっと、ちょうどその最後のビットを見た。大文字と小文字を区別しない比較でも*おそらく*同じように動作し、パフォーマンスに問題がない場合は、大文字のコピーを作成してそれらを比較しても問題は発生しません。大文字と小文字を区別しない比較を一度見たと誓ったかもしれない...


122
「トルコのテスト」を検索してください:)
Jon Skeet

7
一部のフランス語ロケールでは、大文字に分音符号がないため、ToUpper()はToLower()よりも優れているとは限りません。適切なツールが利用可能な場合は、大文字と小文字を区別しないで比較してください。
ブレアコンラッド

5
ToUpperやToLowerを使用せず、Jon Skeetが言ったことを実行してください
Peter Gfader '21

14
2年後に再びこれを見て、新しい反対票を投じました...とにかく、文字列を比較するより良い方法があることに同意します。ただし、すべてのプログラムがローカライズされるわけではなく(ほとんどはローカライズされません)、多くのプログラムが内部または使い捨てのアプリです。私は使い捨てアプリに残されたアドバイスに対するクレジットを期待することはほとんどできないので...私は先に進みます:D
Ed S.

8
「トルコテスト」を検索することは「トルコテスト」を検索することと同じですか?
JackAce

55

.NET Core 2.0以降のみ(現時点)

.NET Coreには、バージョン2.0以降、これに対処するための2つのメソッドがあります。

  • String.Contains(Char、StringComparison
  • String.Contains(String、StringComparison

例:

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

そのうちに、彼らはおそらく.NET標準に進み、そこから、基本クラスライブラリの他のすべての実装に入るでしょう。


1
で今も利用できる.NET標準2.1
パヴェルBulwan

52

答えの1つの問題は、文字列が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;
} 

8
toCheckが空の文字列である場合、Containsのドキュメントに従ってtrueを返す必要があります。
アムラ

3
上記のアムラのコメントに基づいて、提案されたコードを修正する必要はありませんか?そして、これを受け入れられた回答に追加して、最良の応答が最初になるようにしないでください。
David White、

13
toCheckが何であっても、sourceが空の文字列またはnullの場合、これはtrueを返します。それは正しくありません。また、toCheckが空の文字列でソースがnullでない場合、IndexOfはすでにtrueを返します。ここで必要なのはnullのチェックです。(source == null || value == null)がfalseを返すかどうかを提案します。
コリン

2
ソースはnullにできません
Lucas

1
if (string.IsNullOrEmpty(source)) return string.IsNullOrEmpty(toCheck);
カイルデラニー

35

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

なぜ抽象化の別のレイヤーを許可しているのStringComparisonですか?
l --''''''--------- '' '' '' '' '' ''

35

これはクリーンでシンプルです。

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

31
ただし、これはパターンと一致します。場合あなたの例では、fileNamestr特殊な正規表現文字を持っている(例えば*+.、など)あなたはかなりの驚きのためになります。このソリューションを適切なContains関数のように機能させる唯一の方法は、を実行してエスケープfileNamestrすることRegex.Escape(fileNamestr)です。
XåpplI'-I0llwlg'I -

さらに、正規表現の解析と照合は、単純な大文字と小文字を区別しない比較よりもはるかに多くのリソースを消費します
phuclv

29

OrdinalIgnoreCase、CurrentCultureIgnoreCase、またはInvariantCultureIgnoreCase?

これが欠落しているため、どれを使用するかについての推奨事項を以下に示します。

ドス

  • StringComparison.OrdinalIgnoreCase比較に使用して、カルチャに依存しない文字列マッチングの安全なデフォルトとして使用します。
  • StringComparison.OrdinalIgnoreCase速度を上げるには比較を使用します。
  • StringComparison.CurrentCulture-basedユーザーに出力を表示するときに文字列操作を使用します。
  • インバリアントカルチャに基づいて現在の文字列操作の使用を切り替えて、非言語的、StringComparison.Ordinalまたは StringComparison.OrdinalIgnoreCase比較が
    言語的に重要でない場合(記号など)を使用するようにします。
  • 比較のために文字列を正規化するときToUpperInvariantではなく使用しToLowerInvariantます。

しない

  • 文字列比較メカニズムを明示的または暗黙的に指定しない文字列操作には、オーバーロードを使用します。
  • ほとんどの場合、StringComparison.InvariantCultureベースの文字列
    操作を使用します。数少ない例外の1つは、
    言語的には意味がありますが、文化にとらわれないデータを保持することです。

これらのルールに基づいて、使用する必要があります:

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


常に英語の文字列を取得することがわかっている場合はどうでしょうか。どれを使う?
BKSpurgeon 2017年

1
@BKSpurgeon大文字と小文字が区別されない場合はOrdinalIgnoreCaseを使用します
Fabian

20

これらは最も簡単なソリューションです。

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

11

これは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

InStrVisualBasicアセンブリのメソッドは、国際化について懸念がある場合(または再実装できる場合)に最適です。中を見ると、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

ちょうどこのような:

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

3
これはカルチャー固有ではなく、場合によっては失敗することがあります。Culture.CompareInfo.IndexOf(paragraph、word、CompareOptions.IgnoreCase)を使用する必要があります。
hikalkan 14

3
大文字と小文字を区別しない文字列比較を行うときにstring.ToLower()を使用しないのはなぜですか?Tl; Dr 新しいストリングが「製造」されるため、コストがかかります。
リアム

8

これを使って:

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

26
質問者は探してContainsいませんCompare
DuckMaestro

@DuckMaestro、受け入れられた答えはで実装されContainsていIndexOfます。したがって、このアプローチも同様に役立ちます。このページのC#コード例はstring.Compare()を使用しています。SharePointチームの選択です。
バルカンレイヴン2013年

6

これは他の例とよく似ていますが、他の代替手段は通常必要ないため、列挙型を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) )
....

6

RegExを使用すると、これを行うことができます。

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

4
あなたの答えはguptat59のものとまったく同じですが、彼の答えで指摘されたように、これは正規表現に一致するため、テストしている文字列に特別な正規表現文字が含まれている場合、望ましい結果は得られません。
ケーシー

2
これはこの回答の正直なコピーであり、その回答に記載されているのと同じ問題が発生しています
Liam

同意した。正規表現を学ぶ
ジャレッド

5

ここでの答えに基づいて、文字列拡張メソッドを作成して、これをもう少しユーザーフレンドリーにすることができます。

    public static bool ContainsIgnoreCase(this string paragraph, string word)
    {
        return CultureInfo.CurrentCulture.CompareInfo.IndexOf(paragraph, word, CompareOptions.IgnoreCase) >= 0;
    }

1
段落と単語が常にen-USであると仮定
Boris Callens

3
カルチャーをen-USに強制する問題を回避するには、return CultureInfo.CurrentCulture.CompareInfo.IndexOf(paragraph, word, CompareOptions.IgnoreCase) >= 0;代わりにを使用します。
AndrewWhalan

3

渡された文字列が文字列内にあるかどうかを確認する場合は、そのための簡単な方法があります。

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

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

このブール値は、文字列が含まれているかどうかにかかわらず返されます



2
if ("strcmpstring1".IndexOf(Convert.ToString("strcmpstring2"), StringComparison.CurrentCultureIgnoreCase) >= 0){return true;}else{return false;}


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

出力は「リセット」です


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

-4

初心者のための簡単な方法:

title.ToLower().Contains("string");//of course "string" is lowercase.

間違っているだけの反対投票。タイトル= StRiNgの場合はどうなりますか?StRiNg!=文字列およびStRiNg!=文字列
berniefitz

私は間違っていた。次のように回答を編集します。シンプルすぎます。<br/> title.ToLower()。Contains( "string")//もちろん "string"は小文字です
OThạnhLdt
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.