none
stringの置換 RRS feed

  • 質問

  • いつもお世話になります。
    VisualC#2010、WindowsXPでの動作について質問があります。
    stringの置換について教えてください。

    string() lines = {"初代タイガーマスク","飯伏幸太","ブラックタイガー"};
    foreach (string line in lines)
    if (line.Contains("初代タイガーマスク"))
    line += "佐山聡";

    というのは、エラーになるのですが、このような場合はスマートに書くには、どうするものなのでしょうか?

    2011年1月29日 9:29

回答

  • 外池と申します。

    エラーになっている理由はご理解されていますでしょうか? foreach文の対象となっているlineをforeachの中で変更できないからですが・・・、

    代わりに、for文で、インデックスを使ってやれば、更新できますよ?

    for (int i=0;i<lines.Length;i++){
        if(lines[i].Contains(.....)) lines[i]+=....
    }

    てな感じで。


    (ホームページを再開しました)
    • 回答としてマーク d-kot 2011年1月29日 13:59
    2011年1月29日 9:51
  • LINQを使って以下のように書くこともできます。パフォーマンス的には不利かもしれませんが・・・

    lines = lines.Select(p => { if (p == "初代タイガーマスク") return p.Replace(p, p + "佐山聡"); else return p; }).ToArray();
    

     


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
    • 回答としてマーク d-kot 2011年1月29日 14:00
    2011年1月29日 13:44
    モデレータ

  • string message = "";
    string[] lines = {"初代タイガーマスク","飯伏幸太","ブラックタイガー"};
    foreach (string line in lines)
    {
    string lineAdd = "";
    lineAdd = line;
    if (line.Contains("初代タイガーマスク"))
    {
    lineAdd += "佐山聡";
    }
    message += lineAdd + System.Environment.NewLine; ;
    }
    MessageBox.Show(message);
    • 回答としてマーク d-kot 2011年1月31日 12:04
    2011年1月31日 7:39

すべての返信

  • 外池と申します。

    エラーになっている理由はご理解されていますでしょうか? foreach文の対象となっているlineをforeachの中で変更できないからですが・・・、

    代わりに、for文で、インデックスを使ってやれば、更新できますよ?

    for (int i=0;i<lines.Length;i++){
        if(lines[i].Contains(.....)) lines[i]+=....
    }

    てな感じで。


    (ホームページを再開しました)
    • 回答としてマーク d-kot 2011年1月29日 13:59
    2011年1月29日 9:51
  • LINQを使って以下のように書くこともできます。パフォーマンス的には不利かもしれませんが・・・

    lines = lines.Select(p => { if (p == "初代タイガーマスク") return p.Replace(p, p + "佐山聡"); else return p; }).ToArray();
    

     


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
    • 回答としてマーク d-kot 2011年1月29日 14:00
    2011年1月29日 13:44
    モデレータ
  • 外池さん。ありがとうございます。
    foreachの質問を書いたあと、forならできるかもと思って、おなじ書き方をしていました。
    でも、foreachのエラーメッセージの同じものを使い回しているから書き換えられないというのは、意味はわかるけど、どうなのかな~という気がしなくもないですが…。
    同じものを使い回しているからといって、そこに代入したら、その値を元のデータに入れてくれたらいいのになと思うんですけども、そう考えるのは素人でしょうか。素人です。
    trapemiyaさん! ありがとうございます。
    LINQはかっこいいと思って、すこしずつ勉強しているのですが遅々としていて、ひとつひとつとても役に立ちそうです。なるほどこう書くのか~と驚きです。
    2011年1月29日 13:59
  • > 同じものを使い回しているから書き換えられないというのは

    違いますよ。foreach では、シーケンスから要素を取り出す方法は決まっているが、シーケンスへ値を戻す方法が決まっていないからです。 

    配列やリストのようなシンプルな場合だけではなく、foreach の対象になるものは取り出すことしかできないものもあれば、取り出すたびに違う結果になるものもあります。対象がデータベースだったり、場合によってはキーボード入力だったりと、foreach が扱うものは様々です。

    今回の話を foreach に似せて書くと、ローカル変数を用意して

    for (int i = 0; i < lines.Length; i++)
    {
      var line = lines[i];
    
      if (line.Contains("初代タイガーマスク"))
        line += "佐山聡";
    
      // ↓この操作が foreach では定義できない
      lines[i] = line;
    }
    
    

    というようなかんじになると思いますが、このような最後の書き戻しの処理の方法が定義されていないため、foreach では、あやまって書き換えようとしてしまわないようにしてあるのです。書き戻しにも対応した双方向の foreach が欲しい…という言語仕様への要望はあってもいいものですが、あまりみかけませんね。

    2011年1月31日 3:59

  • string message = "";
    string[] lines = {"初代タイガーマスク","飯伏幸太","ブラックタイガー"};
    foreach (string line in lines)
    {
    string lineAdd = "";
    lineAdd = line;
    if (line.Contains("初代タイガーマスク"))
    {
    lineAdd += "佐山聡";
    }
    message += lineAdd + System.Environment.NewLine; ;
    }
    MessageBox.Show(message);
    • 回答としてマーク d-kot 2011年1月31日 12:04
    2011年1月31日 7:39