- ベストアンサー
split
$msg = "aa,bb,cc"; という文字列から真ん中だけを取り出したいとき、 正規表現で、$2という風に取り出すのと、splitを使って my($t1,$t2,$t3) = split(/\,/$msg); として$t2で取り出すのとでは、処理の速度やメモリ使用率においてどちらが効率がいいのでしょうか? また、この場合は、$t1と$t3に無駄な代入が起こってしまいますが、これを解消する手立てはありますでしょうか?
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
ベンチマークを取れば分かりますが、split は文字列の分割に正規表現を使う上に my で変数を用意するので、正規表現だけの方法よりも遅いです。劇的な差ではありませんが。 また、Perlは起動時に変数用のメモリ領域をある程度確保して使いますので、この程度のコードではメモリの使用率とかを気にしても仕方ありません。 ちなみに正規表現でも、( ) を使ってグループ化をするとその都度 $1 などに値を代入するので、後方参照不要なグループには (?: ) を使うと速くなります。 $msg =~ /(?:[^,]+),([^,]+),(?:[^,]+)/; # $1 に 'bb' が入る。 また、「コンマ区切りの3つの文字列」限定でよいなら、 $msg =~ /,([^,]+),/; # 同じく $1 に 'bb' とするとさらに速くなります。 split の時に不要な値のために変数を用意しない方法ですが、これには2通りの方法があります。 1つ目は添え字を使う方法です。 split の結果はリストなので、split 全体を ( ) で囲み、[ ] を使って必要な値を取り出します。 my $t2 = (split /,/, $msg)[1]; 2つ目は不要な変数の変わりに undef を使う方法です。 my (undef, $t2) = split /,/, $msg; このようにすると、1番目の戻値はどこにも格納されません。 どちらを使うかは好みでよいと思いますが、添え字を使った方がコードは短くて済みます。 # localtimeで年月日を取得する例 my (undef, undef, undef, $day, $mon, $year) = localtime; my ($day, $mon, $year) = (localtime)[3..5]; なお、今回のケースならば、substrやindexなどを用いて文字列処理した方が圧倒的に速いです。(Benchmarkで1.5~2倍近く速かったです。) my $t2 = substr($msg, index($msg,',')+1, length($msg)-rindex($msg,',')-1);
その他の回答 (2)
- togino
- ベストアンサー率75% (97/129)
■ 正規表現で取り出す方法 「コンマで区切られた文字列の真ん中」にマッチさせるのですから、当然マッチするかどうかの判断には、多くの比較が行われるでしょう。 従って、処理の速度は遅くなると思います。 ■ split を使って取り出す方法 単純に文字列を前からスキャンして コンマであるかないかを調べるだけなので、処理の速度は速くなりますが、 配列を生成する分、メモリの使用率が増えるでしょう。 ------ メモリを意識するなら正規表現 速度を意識するなら split でしょうか?実験してみないと分かりませんが・・・ # ただ、今のパソコンの性能からすると # ど~でもいいような誤差の範囲だと思いますが # それこそ、その切り出しを何万回もするのであれば # 実際に速度を測られたらよろしいかと > $t1と$t3に無駄な代入が起こってしまいますが、 > これを解消する手立てはありますでしょうか? my($t2) = (split(/\,/, $msg))[1]; でいいと思いますが
- naoto0314
- ベストアンサー率34% (25/73)
数回呼び出す程度であればさほど変わりはありませんが、 正規表現のほうが負荷が若干高く、 split関数のほうがメモリ使用率が若干高くなると思います。