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

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

C# と VB.NET の入門サイト

文字列から特定文字以降の文字列を削除する方法

[トピック内 9 記事 (1 - 9 表示)]  << 0 >>

■88019 / inTopicNo.1)  文字列から特定文字以降の文字列を削除する方法
  
□投稿者/ 河童 (17回)-(2018/07/30(Mon) 11:27:02)

分類:[C#] 

いつも大変お世話になっております。

環境:VS2010

文字列から指定文字以降の文字列を削除したいです。

文字列には氏名を入力しています。
その氏名にコメントを入力したいときは
「氏名:コメント」と入力しています。
コメントがない場合もあります。

文字列に「:」または「:」がある場合に
コロン以降の文字列を削除する方法がわかりません。


1.文字列にコロン(全角・半角)があるか判定。
2.コロンがあるときは文字列からコロン移行を削除。

わからないことは、
removeでどのように削除の開始位置と削除数を
設定するかです。

よろしくお願いします。


//いったん名前保存(スペース削除)
tmp_name = Cell.Replace(" ", "").Replace(" ", "");

//コロン(全角または半角)がある場合は氏名にコメントが付いている
if (tmp_name.Contains(":"))
{
   int len = tmp_name.Length;
   int intFindPos;

   intFindPos = tmp_name.IndexOf(":") + 1;
   tmp_name = tmp_name.Remove(intFindPos, len);
}
else if (tmp_name.Contains(":")) 
{
   int len = tmp_name.Length;
   int intFindPos;
   
   intFindPos = tmp_name.IndexOf(":") + 1;
   tmp_name = tmp_name.Remove(intFindPos, len);  
}

引用返信 編集キー/
■88021 / inTopicNo.2)  Re[1]: 文字列から特定文字以降の文字列を削除する方法
□投稿者/ WebSurfer (1566回)-(2018/07/30(Mon) 11:43:28)
No88019 (河童 さん) に返信

':' または ':' で Split した文字列の配列を作り、配列の一番目の要素を
取得するという方法ではダメなのですか?
引用返信 編集キー/
■88022 / inTopicNo.3)  Re[2]: 文字列から特定文字以降の文字列を削除する方法
□投稿者/ PANG2 (227回)-(2018/07/30(Mon) 11:46:22)
2018/07/30(Mon) 12:53:49 編集(投稿者)
if (tmp_name.Contains(":")) {
	tmp_name = tmp_name.Substring(0, tmp_name.IndexOf(":"));
} else if (tmp_name.Contains(":")) {
	tmp_name = tmp_name.Substring(0, tmp_name.IndexOf(":"));
}

または、

string[] separator = { ":", ":" };
tmp_name = tmp_name.Split(separator, StringSplitOptions.None)[0];

追記

tmp_name = tmp_name.Split(new char[] { ':', ':' })[0];


引用返信 編集キー/
■88024 / inTopicNo.4)  Re[3]: 文字列から特定文字以降の文字列を削除する方法
□投稿者/ とっちゃん (503回)-(2018/07/30(Mon) 11:59:59)
行数少な目で。

var pos = tmp_name.IndexOfAny( new char[]{ ':', ':' } );
if( pos >= 0 )
{
  tmp_name = tmp_name.SubString( 0, pos );
}

引用返信 編集キー/
■88025 / inTopicNo.5)  Re[1]: 文字列から特定文字以降の文字列を削除する方法
□投稿者/ はまぐり (6回)-(2018/07/30(Mon) 12:23:01)
No88019 (河童 さん) に返信

Removeメソッドの引数は
Remove(削除の開始位置, 削除する文字数)

削除の開始位置はコロンの位置なのでIndexOfの値
削除する文字数は文字列の長さから開始位置を引いた値

つまりこう!
tmp_name = tmp_name.Replace(":", ":");
int startIndex = tmp_name.IndexOf(":");
int count = tmp_name.Length - startIndex;
tmp_name = tmp_name.Remove(startIndex, count);

引用返信 編集キー/
■88026 / inTopicNo.6)  Re[2]: 文字列から特定文字以降の文字列を削除する方法
□投稿者/ はまぐり (7回)-(2018/07/30(Mon) 12:24:00)
私が言うのもなんですがいろんなやり方があるもんですね
引用返信 編集キー/
■88031 / inTopicNo.7)  Re[3]: 文字列から特定文字以降の文字列を削除する方法
□投稿者/ とっちゃん (504回)-(2018/07/30(Mon) 13:47:44)
No88019 (河童 さん) に返信

> 文字列から指定文字以降の文字列を削除したいです。
>
> 文字列には氏名を入力しています。
> その氏名にコメントを入力したいときは
> 「氏名:コメント」と入力しています。
> コメントがない場合もあります。
>
> 文字列に「:」または「:」がある場合に
> コロン以降の文字列を削除する方法がわかりません。
>
>
> 1.文字列にコロン(全角・半角)があるか判定。
> 2.コロンがあるときは文字列からコロン移行を削除。
>
さてと。。。ちとまじめなところの突っ込みも。

':' または ':' があるときとなっていますが、両方あった場合はどちらを優先するなどはありますか?

存在する場合、絶対にどちらかしかないのか、あるいは両方存在しうるのかそれによって条件が変わります。

場合によっては、IndexOfAny よりも、IndexOf を使うほうが理に適う場合もあります。

このあたりは仕様として明確になっている必要があります。



さてと。。。ほかの回答も含め。

まずは効率面の改善その1.

先に出ている例に Contains してから、IndexOf している例があります。

これだと実質2回検索することになってしまいます。
Contains は、その集合の中に対象物が含まれているか?という検索のロジックです。

氏名:コメントなので、長さとしてはせいぜい10文字程度なので処理時間で考えれば2回やったって大したことはないんじゃないの?という程度で終わります。
ですが、これが10万回繰り返されているようなところだったらどうでしょう?

こういう何気ない部分というのは、常日頃意識していないと気が付かないことが多いです。
このメソッドは何をするの?どうやってそれを成立させるの?というのはライブラリを使う側としては常に意識を持っておくべき部分といえます。大変ですけどね。


効率面の改善その2.

文字列は、どの言語でも同じと言えますが、内部実装的にはヒープ上から文字列バッファのメモリを確保するという仕組みをとります。
その内部データは複数の文字列クラスで参照される場合があったり、参照しないように完全隠蔽だったりと実装によっていろいろあります。

ですが、異なる文字列の場合は必ず、別途ヒープから必要サイズのメモリを確保し、そこに文字列の内容を必要分だけコピーするという処理を行います。

なので、string を返すメソッドを呼び出す場合、その内部では「必ず新しい文字列」が作られることになります。

Substring であれば、元の文字列の部分的なコピー(より小さいサイズにはなるが別途確保は変わらず)ですし、
Replace なら、文字列から文字を置き換えたもの(文字列同士のReplaceなら、長さが変わる場合もある)です。
Split なら、複数の文字列を作成して、それぞれの新しいバッファにコピーとなります。

また、メソッドを呼び出して得られる結果を一部しか使わないような場合でも、呼び出されたメソッドには判断ができないので
全部の処理をしてしまいます。

Splitして最初の1つしか使わないということであれば、2個目以降のバッファは確保もコピーも無駄な処理となります。

こういった部分もちょこっと意図して置けるようになるとより効率の良いプログラムを作れたりしますよ。

引用返信 編集キー/
■88033 / inTopicNo.8)  Re[4]: 文字列から特定文字以降の文字列を削除する方法
□投稿者/ グッディ (1回)-(2018/07/30(Mon) 15:30:12)
正規表現では1行で以下の通り。
tmp_name = System.Text.RegularExpressions.Regex.Replace(tmp_name, "[::].*$", "");

これは、tmp_nameの最初に登場した半角又は全角コロン以降を削除します。
他の方法よりパフォーマンスは劣るかも知れませんが、
一度に何万件も処理するのでなければ、正規表現を覚えるのも手かも知れません。
引用返信 編集キー/
■88034 / inTopicNo.9)  Re[4]: 文字列から特定文字以降の文字列を削除する方法
□投稿者/ 河童 (18回)-(2018/07/30(Mon) 15:30:39)
皆様、お返事ありがとうございます。

条件として「:」または「:」としたのは、
データ入力者がどちらでも使えるようしたかったからです。
今回のデータ入力はエクセルのセルに直接入力します。
全角を使ってくださいとお願いしても
半角になったりすると予想。

本当にいろいろな方法があるんですね。

その中からどれが一番効率が良いのか
今の私にはわかりません。
奥深く理解できれば、もっとプログラミングが楽しくなるんでしょうね。

今回は、SubstringとIndexOfを使ってみようと思います。

//コロン(全角または半角)がある場合は氏名にコメントが付いている 
if (tmp_name.Contains(":")) 
{
   tmp_name = tmp_name.Substring(0, tmp_name.IndexOf(":"));
} 
else if (tmp_name.Contains(":")) 
{
   tmp_name = tmp_name.Substring(0, tmp_name.IndexOf(":"));
}

解決済み
引用返信 編集キー/

このトピックをツリーで一括表示


トピック内ページ移動 / << 0 >>

このトピックに書きこむ