C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

ログ内検索
  • キーワードを複数指定する場合は 半角スペース で区切ってください。
  • 検索条件は、(AND)=[A かつ B] (OR)=[A または B] となっています。
  • [返信]をクリックすると返信ページへ移動します。
キーワード/ 検索条件 /
検索範囲/ 強調表示/ ON (自動リンクOFF)
結果表示件数/ 記事No検索/ ON
大文字と小文字を区別する

No.44652 の関連記事表示

<< 0 >>
■44652  VBの置換について。ひとつだけ置換は・・・できない??
□投稿者/ やまり -(2009/12/15(Tue) 00:55:32)

    分類:[.NET 全般] 

    畏れ入ります。

    VB.NETの勉強をしております。

    文字列の置換なのですが、ちょっと思いついたことがあって、簡単に実現できるかと思いきや・・・
    できずに恥ずかしながら質問いたします。

    <<やりたいこと>>

    「これ」にマッチしたどれかひとつを「あれ」に変換したい。

    フォーム1・・・入力例「これとこれとこれとこれ」
    フォーム2・・・出力例「これとあれとこれとこれ」


    ---------------
    あまりいい例が思いつかず、わかりにくい例で申し訳ありません。
    もう少し書くとやりたいことは
    ・文字列の置換
    ・検索文字列は複数あり、そのうちひとつだけを置換

    いろいろ考えて、まずは(1)(2)・・のように置換する方法を思いつきました。


    「これとこれとこれとこれ」

    「(1)と(2)と(3)と(4)」
    ↓(1)〜(4)のうちどれかをランダムで→「あれ」に置換
    「(1)と(2)とあれと(4)」
    ↓残った(\d)を「これ」で置換しなおす。
    「これとこれとあれとこれ」

    しかし、VBのreplaceは「すべてを置換」してしまうのですね・・・
    javaだとreplaceallと分かれているのですけど・・・・

    なんだか自分でも考えすぎているような気がしています。


    ・もっと簡単なロジックで実現できそうでしょうか?
    ・マッチした文字列一つ目だけを置換、はできないのでしょうか?

親記事 /過去ログ76より / 関連記事表示
削除チェック/

■44653  Re[1]: VBの置換について。ひとつだけ置換は・・・できない??
□投稿者/ やまり -(2009/12/15(Tue) 01:06:57)
    自己レスです

    http://msdn.microsoft.com/ja-jp/library/system.text.regularexpressions.regex.replace(VS.80).aspx

    Regex.Replace (String, String, Int32) 指定した入力文字列内で正規表現パターンに一致する文字列を、指定した最大回数だけ、指定した置換文字列に置換します。


    のようにありました。
    3つ目の引数に1を指定すればいいのでしょうか・・・?

    これでできればなんとか強引にできそうですが

    できればもっとシンプルに「○番目のマッチを置換」みたいなことができるとうれしいのですが。。。
記事No.44652 のレス /過去ログ76より / 関連記事表示
削除チェック/

■44654  Re[2]: VBの置換について。ひとつだけ置換は・・・できない??
□投稿者/ やまり -(2009/12/15(Tue) 01:45:50)
    もうひとつ自己レスです。

    perlでは$`と$'で前後が取れるようです。

    #!/usr/bin/perl

    my $a="ababab";
    my $cnt=0;

    print $a . "\n";
    while( $a =~ /(a)/g ){
    print qq($cnt : $1\t$`\t$'\n);
    $cnt++;
    }

    こんな風にすると、まっちした前と後が$` $' にはいっているので
    その値を使って2番目にマッチ、とかできそうです。

    VB.NETでこの「$` $'」にあたるものは無いでしょうか・・・
記事No.44652 のレス /過去ログ76より / 関連記事表示
削除チェック/

■44655  Re[3]: VBの置換について。ひとつだけ置換は・・・できない??
□投稿者/ gtk2k -(2009/12/15(Tue) 02:44:14)
    Dim strSrc As String = "これとこれとこれとこれ"
    Dim strMatch As String = "これ"
    Dim strReplace As String = "あれ"
    とした場合

    Dim rnd As New Random()
    Dim ms As MatchCollection = Regex.Matches(strSrc, strMatch)
    Dim idx As Integer = Rnd.Next(ms.Count)
    Dim strDst As String = strSrc.Substring(0, ms(idx).Index) & strReplace & strSrc.Substring(ms(idx).Index + strMatch.Length)

    でとりあえずできる(strDstが結果)。

記事No.44652 のレス /過去ログ76より / 関連記事表示
削除チェック/

■44671  Re[4]: VBの置換について。ひとつだけ置換は・・・できない??
□投稿者/ やまり -(2009/12/15(Tue) 16:10:26)
    gtk2kさん ご回答ありがとうございます。

    やっぱりちょっと考えすぎてしまったようです。とても勉強になります汗


    MatchCollection の使い方がまだ良くわからないのですが、
    countメソッドで、「何番目」というのが取れるのですね・・・

    むりに正規表現を使わない方がわかりやすいですね。

    もう少しじっくりソースを見させて頂きたいと思います。。。



    No44655 (gtk2k さん) に返信
    > Dim strSrc As String = "これとこれとこれとこれ"
    > Dim strMatch As String = "これ"
    > Dim strReplace As String = "あれ"
    > とした場合
    >
    > Dim rnd As New Random()
    > Dim ms As MatchCollection = Regex.Matches(strSrc, strMatch)
    > Dim idx As Integer = Rnd.Next(ms.Count)
    > Dim strDst As String = strSrc.Substring(0, ms(idx).Index) & strReplace & strSrc.Substring(ms(idx).Index + strMatch.Length)
    >
    > でとりあえずできる(strDstが結果)。
    >
    >
記事No.44652 のレス /過去ログ76より / 関連記事表示
削除チェック/

■44659  Re[1]: VBの置換について。ひとつだけ置換は・・・できない??
□投稿者/ 魔界の仮面弁士 -(2009/12/15(Tue) 09:30:22)
    2009/12/15(Tue) 10:09:41 編集(投稿者)

    No44652 (やまり さん) に返信
    > しかし、VBのreplaceは「すべてを置換」してしまうのですね・・・
    > ・マッチした文字列一つ目だけを置換、はできないのでしょうか?
    Dim Src As String = "これとこれとこれとこれ"
    Dim Ret As String = Replace(Src, "これ", "あれ", Count:=1)
    とすれば、1 つだけ置換もできますよ。
    Start:=x で、検索開始位置を調整することもできます。

    3 つ目だけを置換したいなら、
     Ret = Replace(Replace(Src, "これ", "あれ", Count:=3), "あれ", "これ", Count:=2)
    とか。汎用的ではありませんし、文字列によっては使えませんけれども。

    汎用的にするなら、gtk2k さんの方法かな。


    No44653 (やまり さん) に返信
    > できればもっとシンプルに「○番目のマッチを置換」みたいなことができるとうれしいのですが。。。
    その前に、マッチする文字列が○個以上存在するかをチェックする必要がありそうですね。
    事前チェック無しで良いなら、こういう書き方も出来ますけれども。(VB2008)

    'Imports System.Threading
    'Imports System.Text.RegularExpressions

    '3個目の「これ」を「あれ」にする。
    Dim n As Integer = 0 '置換回数カウント用
    Dim ret As String = Regex.Replace("これとこれとこれとこれ", "これ", Function(sz) If(Interlocked.Add(n, 1) = 3, "あれ", "これ"))
記事No.44652 のレス /過去ログ76より / 関連記事表示
削除チェック/

■44672  Re[2]: VBの置換について。ひとつだけ置換は・・・できない??
□投稿者/ やまり -(2009/12/15(Tue) 16:15:21)
    魔界の仮面弁士さん ありがとうございます。


    MSDNも眺めたのですが、Count:= でなんばんめ、というのが取れるのを読み取れませんでした・・・

    > Start:=x で、検索開始位置を調整することもできます。

    そんなこともできるんですね。これも使えそうですね。


    > Function(sz) If(Interlocked.Add(n, 1) = 3

    これがちょっとどういう意味かわからないので、もうすこしじっくり見させていただきたいと思います。

    とっても、感謝です。とりあえず、なんとか出来そうです!!





    No44659 (魔界の仮面弁士 さん) に返信
    > 2009/12/15(Tue) 10:09:41 編集(投稿者)
    >
    > ■No44652 (やまり さん) に返信
    >>しかし、VBのreplaceは「すべてを置換」してしまうのですね・・・
    >>・マッチした文字列一つ目だけを置換、はできないのでしょうか?
    > Dim Src As String = "これとこれとこれとこれ"
    > Dim Ret As String = Replace(Src, "これ", "あれ", Count:=1)
    > とすれば、1 つだけ置換もできますよ。
    > Start:=x で、検索開始位置を調整することもできます。
    >
    > 3 つ目だけを置換したいなら、
    >  Ret = Replace(Replace(Src, "これ", "あれ", Count:=3), "あれ", "これ", Count:=2)
    > とか。汎用的ではありませんし、文字列によっては使えませんけれども。
    >
    > 汎用的にするなら、gtk2k さんの方法かな。
    >
    >
    > ■No44653 (やまり さん) に返信
    >>できればもっとシンプルに「○番目のマッチを置換」みたいなことができるとうれしいのですが。。。
    > その前に、マッチする文字列が○個以上存在するかをチェックする必要がありそうですね。
    > 事前チェック無しで良いなら、こういう書き方も出来ますけれども。(VB2008)
    >
    > 'Imports System.Threading
    > 'Imports System.Text.RegularExpressions
    >
    > '3個目の「これ」を「あれ」にする。
    > Dim n As Integer = 0 '置換回数カウント用
    > Dim ret As String = Regex.Replace("これとこれとこれとこれ", "これ", Function(sz) If(Interlocked.Add(n, 1) = 3, "あれ", "これ"))
記事No.44652 のレス /過去ログ76より / 関連記事表示
削除チェック/

■44675  Re[3]: VBの置換について。ひとつだけ置換は・・・できない??
□投稿者/ 魔界の仮面弁士 -(2009/12/15(Tue) 17:16:56)
    No44672 (やまり さん) に返信
    > MSDNも眺めたのですが、Count:= でなんばんめ、というのが取れるのを読み取れませんでした・・・
    「Replace(Src, "これ", "あれ", Count:=1)」の代わりに、
    「Replace(Src, "これ", "あれ", , 1)」や
    「Replace(Src, "これ", "あれ", 1, 1)」と書く事もできます。
    
    それと先ほど
    >> 汎用的にするなら、gtk2k さんの方法かな。
    と書きましたが、下記のようにする必要がありそうです。
    
    Dim ms As MatchCollection = Regex.Matches(strSrc, Regex.Escape(strMatch))
    Dim strDst As String
    If ms.Count = 0 Then
      strDst = strSrc
    Else
      Dim idx As Integer = rnd.Next(ms.Count)
      strDst = strSrc.Substring(0, ms(idx).Index) & strReplace & strSrc.Substring(ms(idx).Index + strMatch.Length)
    End If
    
    Regex.Escape は、文字列に『(』などが含まれていた場合への備え、
    If 判定は、一回もヒットしなかった場合に対応したものです。
    
    
    >> Start:=x で、検索開始位置を調整することもできます。
    > そんなこともできるんですね。これも使えそうですね。
    Start 引数は、(検索回数ではなく)文字位置を表す引数なので、今回の用途では
    ここに指定すべき数値を調べるためのコードが、別途必要になりますけれどね。
    
    
    >> Function(sz) If(Interlocked.Add(n, 1) = 3
    > これがちょっとどういう意味かわからないので、
    VB のラムダ式では代入文を記述できないので、「n += 1」に相当するコードを、
    Interlocked.Add メソッドで代用しています。
    
    
    ラムダ式だと分かりにくいようであれば、先の Regex.Replace の部分を、
     matchedCount = 0
     ret = Regex.Replace("これとこれとこれとこれ", "これ", AddressOf Matched)
    という記述に読み替えてみてください。
    
    これは、
      文字列中に "これ" が見つかるたびに、Matched メソッドが呼び出され、
      その箇所が Matched メソッドの戻り値によって置換される
    という処理を表しています。
    
    ここでいう matchedCount や Matched は、たとえば下記のように実装されます。
    
     Module Foo
      Public matchedCount As Integer = 0
      Public Function Matched(ByVal m As Match) As String
       matchedCount += 1
       If matchedCount = 3 Then
        Return "あれ"
       Else
        Return "これ"
       End If
      End Function
     End Module
    
    
    そして上記をラムダ式を使って短く記述したものが、先の
     n = 0
     ret = Regex.Replace("これとこれとこれとこれ", "これ", Function(x) If(Interlocked.Add(n, 1) = 3, "あれ", "これ"))
    というわけです。
記事No.44652 のレス /過去ログ76より / 関連記事表示
削除チェック/

■44681  Re[1]: VBの置換について。ひとつだけ置換は・・・できない??
□投稿者/ 魔界の仮面弁士 -(2009/12/15(Tue) 19:35:54)
    No44652 (やまり さん) に返信
    > 文字列の置換なのですが、ちょっと思いついたことがあって、
    
    Replace 系のメソッドを使わずに実装してみました。
    
    -----------
    Dim src As String = "これとこれとこれとこれ"
    Dim before As String = "これ"
    Dim after As String = "あれ"
    
    'Split 関数を使い、「これ」で分断して配列にする
    Dim X As New List(Of String)(Split(src, before))
    
    If X.Count > 2 Then
        '何番目を置き換えるかをランダムに決定
        Dim R As New Random()
        Dim I As Integer = R.Next(X.Count - 1)
    
        'その場所を「あれ」で繋げる
        X(I) &= after & X(I + 1)
    
        '繋いだ場所は取り除く
        X.RemoveAt(I + 1)
    End If
    
    '置き換えなかった場所をすべて「これ」で繋ぎ直して、文字列に戻す
    Dim dst As String = Join(X.ToArray(), before)
記事No.44652 のレス /過去ログ76より / 関連記事表示
削除チェック/



<< 0 >>

パスワード/

- Child Tree -