none
文字列に特定の文字列が存在しているかを調べる方法 RRS feed

  • 質問

  • お世話になります。
    タイトルの通り、特定の文字列が存在しているか調べるとき、以下の方法を使うのですがこれだと一つずつしか調べられず、不便です。
                        If ieurl.Contains("検索する文字列") = True Then
                            MessageBox.Show("発見")
                        Else
                            Exit Sub
                        End If
    一気に複数の文字列を検索でき、TrueとFalseをまとめて判断したいです。
    (わかりにくいのですが、「ABCA」という文字列と「BAC」という文字列が存在するか確認し、あった場合はTrue、なかったらFalseを返す)
    予定では20個くらいあるので提示したコードだと辛いです...。

    どなたか良いコードをお持ちでないでしょうか?よろしくお願いします。

    環境はVB.NET2008、.NETFramework3.5、フォームアプリケーションです。
    2009年4月15日 8:52

回答

  • 「複数の文字列」を配列で用意してやればあとはループをまわすだけだと思いますが、なにかそれで駄目な理由でもありますか?
    // ループの代わりに 拡張メソッドの All や Any を使うって手はありますけど、正直大差ないかな。
    • 回答としてマーク Tanukichi 2009年4月22日 8:33
    2009年4月15日 9:25

  • こんにちは。
    Hongliangさんの様に、文字列を配列で用意して、あとは配列の要素数だけループを回すのがいいと思います。

    Private Function ContainsAnyString(ByVal s As String, ByVal values() As String) As Boolean
            For Each item As String In values
                If s.Contains(item) Then
                    Return True
                End If
            Next
            Return False
     End Function
    • 回答としてマーク Tanukichi 2009年4月22日 8:33
    2009年4月15日 10:13
  • Private Function ContainsAnyString(ByVal s As String, ByVal values() As String) As Boolean

            For Each item As String In values

                If s.Contains(item) Then

                    Return True

                End If

            Next

            Return False

    End Function


    このコードは論理和(いずれかのitemが含まれていればTrue)ですけれども、質問者は論理積(全てのitemが含まれている場合だけTrue)じゃないかな?
    まあ、論理が逆になるように書き換えればすぐですが…。
    解決した場合は、参考になった返信に「回答としてマーク」のボタンを利用して、回答に設定しましょう(複数に設定できます)。
    • 回答としてマーク Tanukichi 2009年4月22日 8:33
    2009年4月15日 14:09
    モデレータ
  • Regexクラスを使って正規表現で書いちゃってもいいと思います。
    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://blogs.wankuma.com/trapemiya/
    • 回答としてマーク Tanukichi 2009年4月22日 8:33
    2009年4月15日 14:50
    モデレータ

  • どうも、かずひろかずです。

    このコードは関数なので、クラスの中(Class ~ End Class)か、モジュールを作って、その中に挿入してださい。
    SubやFunctionの中に入れてはダメですよ?(そこらへんは基礎ですので、本を読んで調べるなりしてください。)

    呼び出すときは、

    Dim any() As String = New String(){"検索", "文字列"}
    
    
    
    If ContainsAnyString("検索する文字列", any) Then
    
        MessageBox.Show("発見")
    
    Else
    
        Exit Sub
    
    End If
    
    
    です。

    だめだった場合はそのコードを適当にぼかしてここに載せてください。
    • 回答としてマーク Tanukichi 2009年4月22日 8:33
    2009年4月16日 10:41
  • クラス名を入れましょう。。。。
    あと、Public Class の 「Public」はあってもOKです。

    ちなみに、どのような場面で使われるアプリケーションかを説明してもらえると助かるのですが・・・
    (フォームアプリケーションであるとか、、、)
    • 回答としてマーク Tanukichi 2009年4月22日 8:33
    2009年4月16日 10:58
  • すると”Class”の部分で”識別子が必要です”と出るのですがまた挿入位置が間違ってしまったのでしょうか?
    聞いてばっかりで申し訳ありませんがよろしくお願いします。
    何でも聞くのではなく、入門書・参考書等で、言語仕様、構文について学ぶようにしましょう。
    Classというキーワードが何を意味するのか、その後に名前を書かないといけないのはなぜか、そう言ったことが聞かずとも分かるようになっていることは、今後プログラムを書いていく上で非常に重要です。
    解決した場合は、参考になった返信に「回答としてマーク」のボタンを利用して、回答に設定しましょう(複数に設定できます)。
    • 回答としてマーク Tanukichi 2009年4月22日 8:33
    2009年4月16日 14:02
    モデレータ
  • ブレークポイントを設定して動きを止めて、ステップ実行でどのような分岐をしているか、どのようなときにReturnしているか確かめてみて下さい。
    デバッグのテクニックを身につけることは、不具合の原因解析等、今後のプログラミングの効率を高めることができるはずです…というより、できないと正直厳しいでしょう。
    解決した場合は、参考になった返信に「回答としてマーク」のボタンを利用して、回答に設定しましょう(複数に設定できます)。
    • 回答としてマーク Tanukichi 2009年4月22日 8:33
    2009年4月16日 14:26
    モデレータ
  • ブレークポイントをいろいろ設置した結果、
    If ContainsAnyString(Live, any) Then
    の条件が満たされていないのにもかかわらず
    Else
    のほうに回らず
    MessageBox.Show("発見")
    に回ってしまっています。
    私がブレークポイントを張って、動きを見て欲しいと言ったのは、ContainsAnyStringメソッドの中身です。
    そこで、Return Trueなのか、Return Falseなのか、せめてどちらかぐらいは確認して下さい。

    そして、想定外にReturn Trueに来ているのであれば、そのときの s と item の中身を確認して下さい。

    ちなみに、下記のようなテストをする限りは再現しません。

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim live As String = "ABCDEFG"
        Dim any As String() = {"aaa", "bbb"}
    
        If ContainsAnyString(Live, any) Then
            '検索される文字列:live 検索する語句:any
            MessageBox.Show("発見")
            Exit Sub
        Else
            Exit Sub
        End If
    End Sub
    


    # anyの最後に"" (空の文字列) が入っているとかそういうオチはないかな…さすがに。


    解決した場合は、参考になった返信に「回答としてマーク」のボタンを利用して、回答に設定しましょう(複数に設定できます)。
    • 回答としてマーク Tanukichi 2009年4月22日 8:33
    2009年4月16日 14:58
    モデレータ
  • 配列に含まれている要素がfor eachによってitemに一つずつ設定されつつ、ループで繰り返されるものです。
    ブレークで止めた時にカーソルを合わせるとitemがどんな値になっているか、分かると思います。

    繰り返しになりますが、基礎をもっと固めたり、自分が書いたコードが何をしているか分かるようになってください。
    解決した場合は、参考になった返信に「回答としてマーク」のボタンを利用して、回答に設定しましょう(複数に設定できます)。
    • 回答としてマーク Tanukichi 2009年4月22日 8:33
    2009年4月17日 3:33
    モデレータ
  • If item.Contains(item) Then
    item に item が含まれるのは自明なので、
    このままでは常に Then が実行されてしまいますね。

    virtual void
    • 編集済み Abstrakt 2009年4月17日 5:49 コードの位置を勘違いした(?)
    • 回答としてマーク Tanukichi 2009年4月22日 8:33
    2009年4月17日 5:39
  • itemにはvaluesの要素が代入されます。

    For Each item As String In values
    とすると、
    values = "aaa", "bbb"
    なら、
    ループ一回目:
    item = "aaa"
    二回目:
    item = "bbb"
    となります。

    -----------------------------------------------------
    http://homepage1.nifty.com/rucio/main/VBdotNet/Samples201/Sample205ForEachNext.htm
    ↑ Visual Basic 中学校さんのサイトです。
    -----------------------------------------------------

    これを実行すればTrueが返ってくるはずですよ?↓
    Private Sub Button1_Click(ByVal sender As System.Object, _
     ByVal e As System.EventArgs) Handles Button1.Click
            Dim any() As String = New String() {"今日", "一日"}
            Dim live As String = "こんにちは。今日はいい一日でしたか?"
            If ContainsAnyString(live, any) Then
                MessageBox.Show("発見")
                Exit Sub
            Else
                Exit Sub
            End If
    
        End Sub
    
        Private Function ContainsAnyString(ByVal s As String, _
     ByVal values() As String) As Boolean
            For Each item As String In values
                If s.Contains(item) Then
                    Return True
                End If
            Next
            Return False
        End Function
    • 回答としてマーク Tanukichi 2009年4月22日 8:33
    2009年4月17日 11:23
  • Regexクラスを使って正規表現で書いちゃってもいいと思います。

    配列を使用した検索方法が続いていますので、正規表現を使った例は私のブログの方に掲載しておきました。

    正規表現を使って、ある文字列にいくつかの特定の文字列が含まれているかを調べる
    http://blogs.wankuma.com/trapemiya/archive/2009/04/18/171635.aspx
    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://blogs.wankuma.com/trapemiya/
    • 回答としてマーク Tanukichi 2009年4月22日 8:33
    2009年4月17日 15:28
    モデレータ

すべての返信

  • 「複数の文字列」を配列で用意してやればあとはループをまわすだけだと思いますが、なにかそれで駄目な理由でもありますか?
    // ループの代わりに 拡張メソッドの All や Any を使うって手はありますけど、正直大差ないかな。
    • 回答としてマーク Tanukichi 2009年4月22日 8:33
    2009年4月15日 9:25

  • こんにちは。
    Hongliangさんの様に、文字列を配列で用意して、あとは配列の要素数だけループを回すのがいいと思います。

    Private Function ContainsAnyString(ByVal s As String, ByVal values() As String) As Boolean
            For Each item As String In values
                If s.Contains(item) Then
                    Return True
                End If
            Next
            Return False
     End Function
    • 回答としてマーク Tanukichi 2009年4月22日 8:33
    2009年4月15日 10:13
  • Private Function ContainsAnyString(ByVal s As String, ByVal values() As String) As Boolean

            For Each item As String In values

                If s.Contains(item) Then

                    Return True

                End If

            Next

            Return False

    End Function


    このコードは論理和(いずれかのitemが含まれていればTrue)ですけれども、質問者は論理積(全てのitemが含まれている場合だけTrue)じゃないかな?
    まあ、論理が逆になるように書き換えればすぐですが…。
    解決した場合は、参考になった返信に「回答としてマーク」のボタンを利用して、回答に設定しましょう(複数に設定できます)。
    • 回答としてマーク Tanukichi 2009年4月22日 8:33
    2009年4月15日 14:09
    モデレータ
  • Regexクラスを使って正規表現で書いちゃってもいいと思います。
    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://blogs.wankuma.com/trapemiya/
    • 回答としてマーク Tanukichi 2009年4月22日 8:33
    2009年4月15日 14:50
    モデレータ
  • みなさん、お忙しい中回答ありがとうございます。

    かずひろかずさんのコードはどこに挿入すればいいのでしょうか?
    ”名前"values"は宣言されていません”や"エラー 1 Sub または Set の 'Return' ステートメントで値を返すことはできません。 ”など出るのですが...

    Azuleanさん
    >論理積(全てのitemが含まれている場合だけTrue)じゃないかな
    説明が明確でなくてすみません。
    複数の文字列の中でどれか一個同じであればTrueを返したいです。
    2009年4月16日 8:57

  • どうも、かずひろかずです。

    このコードは関数なので、クラスの中(Class ~ End Class)か、モジュールを作って、その中に挿入してださい。
    SubやFunctionの中に入れてはダメですよ?(そこらへんは基礎ですので、本を読んで調べるなりしてください。)

    呼び出すときは、

    Dim any() As String = New String(){"検索", "文字列"}
    
    
    
    If ContainsAnyString("検索する文字列", any) Then
    
        MessageBox.Show("発見")
    
    Else
    
        Exit Sub
    
    End If
    
    
    です。

    だめだった場合はそのコードを適当にぼかしてここに載せてください。
    • 回答としてマーク Tanukichi 2009年4月22日 8:33
    2009年4月16日 10:41
  • Public Classに入れてました...
    教えていただいた通りに次の通りにしました
        Class
            Private Function ContainsAnyString(ByVal s As String, ByVal values() As String) As Boolean
                For Each item As String In values
                    If s.Contains(item) Then
                        Return True
                    End If
                Next
                Return False
            End Function
        End Class
    すると”Class”の部分で”識別子が必要です”と出るのですがまた挿入位置が間違ってしまったのでしょうか?
    聞いてばっかりで申し訳ありませんがよろしくお願いします。
    2009年4月16日 10:51
  • クラス名を入れましょう。。。。
    あと、Public Class の 「Public」はあってもOKです。

    ちなみに、どのような場面で使われるアプリケーションかを説明してもらえると助かるのですが・・・
    (フォームアプリケーションであるとか、、、)
    • 回答としてマーク Tanukichi 2009年4月22日 8:33
    2009年4月16日 10:58
  • すると”Class”の部分で”識別子が必要です”と出るのですがまた挿入位置が間違ってしまったのでしょうか?
    聞いてばっかりで申し訳ありませんがよろしくお願いします。
    何でも聞くのではなく、入門書・参考書等で、言語仕様、構文について学ぶようにしましょう。
    Classというキーワードが何を意味するのか、その後に名前を書かないといけないのはなぜか、そう言ったことが聞かずとも分かるようになっていることは、今後プログラムを書いていく上で非常に重要です。
    解決した場合は、参考になった返信に「回答としてマーク」のボタンを利用して、回答に設定しましょう(複数に設定できます)。
    • 回答としてマーク Tanukichi 2009年4月22日 8:33
    2009年4月16日 14:02
    モデレータ
  • あれ?上記の件は解決しましたという書き込みをしたはずなのですがなぜか消えています...
    おかしいです。ちゃんと投稿ボタンを押し、表示されているのを確認したのですが...。
    もう一度思い出して書いてみます。

    回答ありがとうございます。
    上記の件は無事解決しましたが、新たな問題が生まれてしまいました...。
                        If ContainsAnyString(Live, any) Then
    '検索される文字列:live 検索する語句:any
                            MessageBox.Show("発見")
                            Exit Sub
                        Else
                            Exit Sub
                        End If
    としたのですがLiveにany内の語句がないのにもかかわらず”発見”が表示されてしまいます。
    これはどのようにしたら解決できますか?知恵がなくて申し訳ないです...。
    2009年4月16日 14:16
  • ブレークポイントを設定して動きを止めて、ステップ実行でどのような分岐をしているか、どのようなときにReturnしているか確かめてみて下さい。
    デバッグのテクニックを身につけることは、不具合の原因解析等、今後のプログラミングの効率を高めることができるはずです…というより、できないと正直厳しいでしょう。
    解決した場合は、参考になった返信に「回答としてマーク」のボタンを利用して、回答に設定しましょう(複数に設定できます)。
    • 回答としてマーク Tanukichi 2009年4月22日 8:33
    2009年4月16日 14:26
    モデレータ
  • ブレークポイントをいろいろ設置した結果、
    If ContainsAnyString(Live, any) Then
    の条件が満たされていないのにもかかわらず
    Else
    のほうに回らず
    MessageBox.Show("発見")
    に回ってしまっています。

    自分で次のようなコードを試しましたが該当していても何もなりませんでした...。
                       If Live.Contains(any(0)) = True Then
                           MessageBox.Show("発見")
                        Else
                          Exit Sub
                       End If
    この場合、どのようにしたらよいのでしょうか?よろしくお願いします。
    2009年4月16日 14:47
  • ブレークポイントをいろいろ設置した結果、
    If ContainsAnyString(Live, any) Then
    の条件が満たされていないのにもかかわらず
    Else
    のほうに回らず
    MessageBox.Show("発見")
    に回ってしまっています。
    私がブレークポイントを張って、動きを見て欲しいと言ったのは、ContainsAnyStringメソッドの中身です。
    そこで、Return Trueなのか、Return Falseなのか、せめてどちらかぐらいは確認して下さい。

    そして、想定外にReturn Trueに来ているのであれば、そのときの s と item の中身を確認して下さい。

    ちなみに、下記のようなテストをする限りは再現しません。

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim live As String = "ABCDEFG"
        Dim any As String() = {"aaa", "bbb"}
    
        If ContainsAnyString(Live, any) Then
            '検索される文字列:live 検索する語句:any
            MessageBox.Show("発見")
            Exit Sub
        Else
            Exit Sub
        End If
    End Sub
    


    # anyの最後に"" (空の文字列) が入っているとかそういうオチはないかな…さすがに。


    解決した場合は、参考になった返信に「回答としてマーク」のボタンを利用して、回答に設定しましょう(複数に設定できます)。
    • 回答としてマーク Tanukichi 2009年4月22日 8:33
    2009年4月16日 14:58
    モデレータ
  • MessageBox.Show("発見")

    For Each item As String In values

    If item.Contains(item) Then

    Return True

    End Function

    無限ループ

    でした。
    あと、"item"は何の役割を果たしているのでしょうか?

    回答、よろしくお願いします。
    2009年4月16日 15:02
  • 配列に含まれている要素がfor eachによってitemに一つずつ設定されつつ、ループで繰り返されるものです。
    ブレークで止めた時にカーソルを合わせるとitemがどんな値になっているか、分かると思います。

    繰り返しになりますが、基礎をもっと固めたり、自分が書いたコードが何をしているか分かるようになってください。
    解決した場合は、参考になった返信に「回答としてマーク」のボタンを利用して、回答に設定しましょう(複数に設定できます)。
    • 回答としてマーク Tanukichi 2009年4月22日 8:33
    2009年4月17日 3:33
    モデレータ
  • If item.Contains(item) Then
    item に item が含まれるのは自明なので、
    このままでは常に Then が実行されてしまいますね。

    virtual void
    • 編集済み Abstrakt 2009年4月17日 5:49 コードの位置を勘違いした(?)
    • 回答としてマーク Tanukichi 2009年4月22日 8:33
    2009年4月17日 5:39
  • itemにはvaluesの要素が代入されます。

    For Each item As String In values
    とすると、
    values = "aaa", "bbb"
    なら、
    ループ一回目:
    item = "aaa"
    二回目:
    item = "bbb"
    となります。

    -----------------------------------------------------
    http://homepage1.nifty.com/rucio/main/VBdotNet/Samples201/Sample205ForEachNext.htm
    ↑ Visual Basic 中学校さんのサイトです。
    -----------------------------------------------------

    これを実行すればTrueが返ってくるはずですよ?↓
    Private Sub Button1_Click(ByVal sender As System.Object, _
     ByVal e As System.EventArgs) Handles Button1.Click
            Dim any() As String = New String() {"今日", "一日"}
            Dim live As String = "こんにちは。今日はいい一日でしたか?"
            If ContainsAnyString(live, any) Then
                MessageBox.Show("発見")
                Exit Sub
            Else
                Exit Sub
            End If
    
        End Sub
    
        Private Function ContainsAnyString(ByVal s As String, _
     ByVal values() As String) As Boolean
            For Each item As String In values
                If s.Contains(item) Then
                    Return True
                End If
            Next
            Return False
        End Function
    • 回答としてマーク Tanukichi 2009年4月22日 8:33
    2009年4月17日 11:23
  • Regexクラスを使って正規表現で書いちゃってもいいと思います。

    配列を使用した検索方法が続いていますので、正規表現を使った例は私のブログの方に掲載しておきました。

    正規表現を使って、ある文字列にいくつかの特定の文字列が含まれているかを調べる
    http://blogs.wankuma.com/trapemiya/archive/2009/04/18/171635.aspx
    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://blogs.wankuma.com/trapemiya/
    • 回答としてマーク Tanukichi 2009年4月22日 8:33
    2009年4月17日 15:28
    モデレータ
  • 理由はわからないのですがExit Subを削除したらうまくいくようになりました。
    みなさん、お忙しい中ありがとうございました。
    2009年4月22日 8:32
  • 理由はわからないのですがExit Subを削除したらうまくいくようになりました。
    その前後によってどのように変わったからうまくいったかをちゃんと調べましょう。
    そうやって原因を調べて解決していくようにしないと、今後も「よく分からないけどうまく動かない」といったトラブルを招く恐れがあります。
    解決した場合は、参考になった返信に「回答としてマーク」のボタンを利用して、回答に設定しましょう(複数に設定できます)。
    2009年4月22日 13:55
    モデレータ