• ベストアンサー

split

$msg = "aa,bb,cc"; という文字列から真ん中だけを取り出したいとき、 正規表現で、$2という風に取り出すのと、splitを使って my($t1,$t2,$t3) = split(/\,/$msg); として$t2で取り出すのとでは、処理の速度やメモリ使用率においてどちらが効率がいいのでしょうか? また、この場合は、$t1と$t3に無駄な代入が起こってしまいますが、これを解消する手立てはありますでしょうか?

  • arcsin
  • お礼率46% (194/417)
  • Perl
  • 回答数3
  • ありがとう数3

質問者が選んだベストアンサー

  • ベストアンサー
  • leaz024
  • ベストアンサー率75% (398/526)
回答No.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)
回答No.2

■ 正規表現で取り出す方法 「コンマで区切られた文字列の真ん中」にマッチさせるのですから、当然マッチするかどうかの判断には、多くの比較が行われるでしょう。 従って、処理の速度は遅くなると思います。 ■ split を使って取り出す方法 単純に文字列を前からスキャンして コンマであるかないかを調べるだけなので、処理の速度は速くなりますが、 配列を生成する分、メモリの使用率が増えるでしょう。 ------ メモリを意識するなら正規表現 速度を意識するなら split でしょうか?実験してみないと分かりませんが・・・ # ただ、今のパソコンの性能からすると # ど~でもいいような誤差の範囲だと思いますが # それこそ、その切り出しを何万回もするのであれば # 実際に速度を測られたらよろしいかと > $t1と$t3に無駄な代入が起こってしまいますが、 > これを解消する手立てはありますでしょうか? my($t2) = (split(/\,/, $msg))[1]; でいいと思いますが

  • naoto0314
  • ベストアンサー率34% (25/73)
回答No.1

数回呼び出す程度であればさほど変わりはありませんが、 正規表現のほうが負荷が若干高く、 split関数のほうがメモリ使用率が若干高くなると思います。

関連するQ&A

  • splitを使って、コンマ区切りで変数を出したいです。

    こんにちは。 いつもお世話になっております。 データファイルを開き、一覧を $all_dataに入れました。 その後、 ($aa,$bb,$cc) = split(/\,/,$all_data); と書いて、変数$aa $bb $cc へ入れたいのです。 3個程度の変数に格納するのは、問題なく出来たのですが、 ($aa,$bb,$cc)を、($aa,$bb,…36個)の変数で指定した途端 $all_data の最後のデータのみ$aa $bbに入り、その後の $cc以降の変数は、空白となってしまいました。 一覧を、$all_dataに入れた後、print で一覧を出してみたのですが、 あいう,えお,かき,くけこ,…<略>… と、36個の文字が,で区切られて出てきました。 何が悪いのか判らなくて、途方にくれております…。 split を使って36個もの変数に直そうとするのが 間違いなのかな、と思って @array = split(/\,/,$all_data); として、 $aa = $array[0]; $bb = $array[1]; としてみたのですが、$all_dataの最後と、最後から 二つ目のデータが$aa $bb に入り、$cc 以降は 空白となってしまいました……。 どうか、ご指導よろしくお願い申し上げます。

    • ベストアンサー
    • Perl
  • 3つの連想配列を交互に代入して、新しい連想配列を作りたい

    PHP Version 5.1.6を使っています。 それぞれの連想配列を先頭から順番に交互に代入したいのですが、 どのようなプログラムでできるのでしょうか? $arr1 = array(a1=>"aa1", a2=>"aa2", a3=>"aa3"); $arr2 = array(b1=>"bb1", b2=>"bb2", b3=>"bb3"); $arr3 = array(c1=>"cc1", c2=>"cc2", c3=>"cc3"); 代入後 $new_arr = array(  a1=>"aa1",  b1=>"bb1",  c1=>"cc1",  a2=>"aa2",  b2=>"bb2",  c2=>"cc2",  a3=>"aa3",  b3=>"bb3",  c3=>"cc3", );

    • ベストアンサー
    • PHP
  • split と 正規表現による分割

    http://oshiete1.goo.ne.jp/kotaeru.php3?q=964020 にて同じような質問をしたのですが、ご回答と自分での検証で食い違いが起きたので質問させていただきます。 splitを用いた分割と正規表現を用いた分割のどちらが速いかというものです。 #####test.txt### ... <!--line--> ... <!--line--> .... ################ というファイルを$lineという変数に入れ、 ********************************************** sub seiki { my $a,$b,$c; if($line=~ /(.*)<!--line-->\n(.*)<!--line-->\n(.*)/s){ $a=$1; $b=$2; $c=$3; } ********************************************** と ********************************************** sub split { my($a,$b,$c){split("<!--line-->\n",$line);} } ********************************************** をBenchmarkモジュールを用いて、速度比較をしてみたところ、splitの方が4倍程速い結果が出ました。実際に用いたtest.txtのサイズは10KBです。 前回質問したときのご回答では、正規表現のほうが早いというご意見をいただいたのですが、本当のところはどちらなのでしょうか

    • ベストアンサー
    • Perl
  • 正規表現ですが・・・

    正規表現なんですが(Perlです。) Aa_abcd_aa.txt Aa_abcd_bb.txt Aa_abcd_cc.txt Bb_abcd.txt 上記のabcdの部分をマッチさせるために (?<=Aa_|Bb_).*(?=_aa|_bb|_cc|\.txt) としてみましたが、これでは Aa_abcd_aa.txt Aa_abcd_bb.txt Aa_abcd_cc.txt のabcd_aaやabcd_bbやabcd_ccとマッチしてしまいます。 なにかよい表現の仕方はありますか? まとめてマッチさせる表現が知りたいです。

  • 変数に改行を含む文字列を代入

    変数に改行を含む文字列を代入したいです。 具体的には echo $KAIGYO AA BB CC DD となるような $KAIGYOを作りたいです。 どのようにしたらよいでしょうか?

  • コマンドプロンプトのバッチファイルについて

    ディレクトリ1に以下のようなファイルがあります。  "file01_05_aa.jpg"  "file01_05_bb.jpg"  "file01_05_cc.jpg"  "file21_04_aa.jpg"  "file21_04_bb.jpg"  "file21_04_cc.jpg"  "file31_03_aa.jpg"  "file31_03_bb.jpg"  "file31_03_cc.jpg" これらのファイル形式は (file)(XX)_(XX)_(XX).jpg これらの中からこの正規表現でヒットするファイルのみ指定した別ディレクトリにコピーしたいです。 file\d\d_(05|03)_(aa|cc)\.jpg Windowsのコマンドプロンプトで実現可能でしょうか。可能であればコマンド列を教えてください。 (cygwinでも良いです。) よろしくお願いいたします。

  • UPDATEについて(結合による)

    次のような操作がしたいのですが・・・ Test1 t1 t2 1 A 2 B Test2 tt1 tt2 tt3 1 1 AA 1 2 BB 2 1 CC 結果 Test1とTest2を関係付けて(Test.t1=Test2.tt1のinnerjoin) Test2.tt3が少なくともAAである場合に Test1.t2をDにしたいのです。 アドバイスあれば、宜しくお願いします。

  • エンディアンについて

    すみません。 教えてください。 リトルエンディアンからビッグエンディアンに変換しないと いけません。 エンディアンについては勉強したつもりですが、 どうしてもわからないことがあります。 ご存知の方、教えていただせんか? CPUはリトルです。 まず、エンディアンの違いについては 以下のように認識しています。 x = 0xAABBCCDD メモリの配置方法が、 トリルだと DD CC BB AA ビックだと AA BB CC DD だと思っています。32ビットの場合です。 で、これを変換するには、htonlで変換可能だと思っっています。 (試したところ可能でした) で次に、32ビットを超えるデータ、たとえば100バイトとかを mallocにして変数に代入しました。 この時はエンディアン変換(ファイルに出力する際)は必要ないのでしょうか? 試しに出力すると、 x = 0x AA BB CC DD EE FF GG ・・・・・・ZZ (100バイトと仮定) バイナリでの出力結果は AA BB CC DD EE FF GG ・・・・・となっていました。 私の認識だと、本CPUはリトルエンディアンのため、 ZZ ・・・・・・・・ DD CC BB AA (四バイトずつ反転しているデータ) が出力されるものと思っていました。(反転してメモリに格納されるため) リトル/ビックを意識しないといけないのは、 2バイトや4バイトの時のみで、それを超える大きなデータ(100バイト)などは 意識せず、そのままバイナリ出力しても、ビックエンディアンで出力されると いうことでよろしいでしょうか? そうなると、エンディアンってなんだんだ???と混乱しています。 わかりにくい説明で大変申し訳ござませんが、 よろしくお願いいたします。

  • SQLで優先順位が高いレコードを抽出する方法

    こんにちは。 あるテーブル"T_A"が有り、 そのテーブルにカラム"C1"、"C2"が有ります。 テーブル"T_A"にレコードが以下の用に登録されていると仮定します。 C1|C2 ----- AA|S AA|P BB|R BB|S CC|S ※C2に登録されている値は抽出する優先順位が有り、 R:1 P:2 S:3 Rが一番優先順位が高く、Sが優先順位が最も低いです。 この条件から、C1の値が同じレコードに対して、C2の優先順位が 最も高いレコードを抽出したいです。 欲しい結果↓ C1|C2 ----- AA|P BB|R CC|S

  • 正規表現で行ではなく単語のみをファイル化したい

    正規表現で電話やアドレスを検索するとその行丸々表示されてしまいます。 [例]'[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+' [結果] 何々、xx@aa,bb,cc 正規表現の単語部分(何々、を除いた部分)だけを取り出すにはどうすればいいのですか お願いします。

専門家に質問してみよう