電子書籍の厳選無料作品が豊富!

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

phpにて、文中にキーワードがあるかどうか判定し、そのキーワードによって処理を変えていくというプログラムを作成しています。
preg_matchまたはstrposによるキーワード判定と、switchによる処理を組み合わせたものです。


//判定対象となる文章
$text = "判定対象となる文章";

//判定キーワードの設定
$word1 = "/キーワード1|きーわーど1|keyword1/";
$word2 = "/キーワード2|きーわーど2|keyword2/";
.
.(中略)
.
$word30 = "/キーワード30|きーわーど30|keyword30/";


//判定処理
switch (true) {

case preg_match($word1, $text):
echo "キーワード1に該当します"
break;

case preg_match($word2, $text):
echo "キーワード2に該当します"
break;
.
.(大量のcase)
.
case preg_match($word30, $text) && preg_match($word1, $text):
echo "キーワード1かつキーワード30に該当します"
break;
};



ざっと書くとこのような構造になっています。
しかしキーワード分岐がかなり多岐に渡っている状態で、switch文の後半のcaseに該当する場合になってくると速度もかなり遅く感じます。
どうにかもう少し高速化したいなあと考えているのですが、何か良い方法はありますでしょうか?
よろしくお願い致します。

A 回答 (3件)

一個のswitch文だと、最初のcaseで、"キーワード1" にマッチすると、ループを抜けるので、もし"キーワード30"も同時に含まれていたとしても、最後の"キーワード1かつキーワード30" は、実行されないと思います。


キーワードを全部patternに放り込めばいいのでは?と最初思ったのだけど、キーワードのグループ分けをしたいのかと推測。
グループ分け用にhash配列を作成してpreg_match_allを使ってみた
<?php
$text = 'キー3判定きー1対象となるけーkey3文章key4';
/* グループ分け用hash配列 キーにkeyword文字列, 値にグループ番号 */
$keyhash = array( 'key1'=>1, 'きー1'=>1, 'キー1'=>1
, 'key2'=>2, 'きー2'=>2, 'キー2'=>2
, 'key3'=>3, 'きー3'=>3, 'キー3'=>3
, 'key4'=>4, 'きー4'=>4, 'キー4'=>4
);
$pattern = '/('. implode( '|' , array_keys($keyhash)) .')/';
$n = preg_match_all($pattern , $text, $matches, PREG_OFFSET_CAPTURE);
echo "<pre>: text : $text\n: pattern : $pattern\n: matches : ";
var_dump($matches);
echo '</pre>';
$match_group = array();
if( $n>0){
echo "\n<dl>";
for( $i=0; $i<$n; $i++){
echo "<dt>match $i :</dt><dd>keyword : {$matches[0][$i][0]}
, 文字列のオフセット {$matches[0][$i][1]}, group {$keyhash[ $matches[0][$i][0]]}</dd>";
/* $keyhash[ $matches[0][$i][0] ] でマッチしたグループ番号がわかるので適宜処理分岐する */
$g = $keyhash[ $matches[0][$i][0]];
if(isset( $match_group[$g] )) {
$match_group[$g] ++;
}else{
$match_group[$g] = 1;
}
}
echo "</dl>\n";
}else{
echo '一個もマッチしませんでした';
}
echo '<pre>match group list : ';
var_dump($match_group);
echo '</pre>';
?>
    • good
    • 0
この回答へのお礼

お礼が大変遅くなりまして申し訳ありませんでした。
回答頂いたコードを応用し、無事目的のものを作成することができました!
ありがとうございました。

お礼日時:2009/09/23 14:38

そういえば、COBOLやCやVBなどコンパイラでもスイッチ文に匹敵する構文が遅くなると使用禁止になったことあります。



そんなに凝って難しく作らないで、単純にIF文にしてしまったら良くないですか?
IF文をネストとする必要はありません。
メッセージは文字列結合して積み上げたり、メッセージが出た回数をカウントしたら良いし。

どうせ、判定はしなくちゃ駄目なのなら、ストレートなIF文が良いと思います。
    • good
    • 0
この回答へのお礼

回答ありがとうございました。
参考になりました!

お礼日時:2009/09/23 14:39

これってswitchでやることでしょうか?


あえてやるならdo~while(false)のような・・・

それはさておき、前から順番にヒットするまでチェックをする
のですから後ろのほうでヒットすればその分おそくなるのは
仕方がないことだと思います

また正規表現はかならずしも速い検索方法ではありませんので
strpos()などでチェックする方が速くなる場合もあるかもしれません。
    • good
    • 0
この回答へのお礼

回答ありがとうございました。
参考になりました!

お礼日時:2009/09/23 14:39

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!